iOS 6 MKMapView seems to be using the tons of memory, when we starts zooming and playing around with the Map View in our application(for around 7-10 mins), When we come out of the controller which has MKMapView, its some how not releasing the total memory(I am using ARC in my App). I am allocating and initializing the MKMapView thru NIB.
Controller 1 -->Controller 2 (has MKMapView)
1.5MB -->40-60MB (I have used the Instruments to find out leaks, but of no use)
When i come back to Controller1 the live bytes seems to be 7-10MB, after every visit to controller 2 there is around 2-3MB of increment in the Live Bytes, after some time it crashes the application, in console it says "Received Memory Warning". can any one please help? If you need any more info please let me know. Thanks in Advance.
This is because of the way MKMapView works. There's an operation pending, so MapKit is retaining the MKMapView and it hasn't actually been deallocated yet. That isn't itself a problem. The problem is that it's still sending messages to your delegate.
The workaround is simple: As part of your view controller's cleanup set the map view's delegate to nil, which will prevent MKMapView from sending messages to it.
This is documented in MKMapViewDelegate Protocol Reference:
Before releasing an MKMapView object for which you have set a delegate, remember to set that object’s delegate property to nil. One place you can do this is in the dealloc method where you dispose of the map view.
Edit: Give Oscar an upvote as well, just below, who provided the documentation quote here.
Given ARC, I suggest this means you should set your map view's delegate to nil in your view controller's dealloc.
You can do some thing like this which resolves my issue . Change the type of map helps it too.
- (void)applyMapViewMemoryHotFix{
switch (self.mapView.mapView.mapType) {
case MKMapTypeHybrid:
{
self.mapView.mapView.mapType = MKMapTypeStandard;
}
break;
case MKMapTypeStandard:
{
self.mapView.mapView.mapType = MKMapTypeHybrid;
}
break;
default:
break;
}
self.mapView.showsUserLocation = NO;
self.mapView.delegate = nil;
[self.mapView removeFromSuperview];
self.mapView = nil;
}
-(void)viewDidDisappear:(BOOL)animated
{
[self applyMapViewMemoryHotFix];
}
Related
The watch app I am developing is not using ARC. And so I releases all the properties of objects in each interface in dealloc as below.
-(void)dealloc {
[obj1 release];
[obj2 release];
...
[super dealloc];
}
This causes crash when i close the interface (for example to go back to main interface). Why is this so?
Retains and releases need to be balanced in the context of your class. Probably you didn't retain when you assigned to one of those instance variables, and thus it's an over-release. You can try enabling zombies to catch the message to a deallocated instance if that's the case.
I have been trying to find out what is causing this crash.
My main view controller has some code like this to start camera picker.
pickerControl = [[UIImagePickerController alloc] init];
pickerControl.sourceType = UIImagePickerControllerSourceTypeCamera;
pickerControl.allowsEditing = NO;
pickerControl.wantsFullScreenLayout = YES;
pickerControl.showsCameraControls = NO;
pickerControl.cameraOverlayView = overlay;
pickerControl.delegate = self;
overlay.delegate = self;
[self presentViewController:pickerControl animated:NO completion:nil];
The overlay is a view with a few buttons at the bottom. one of them is calling back to take picture.. and the call back will call takePicture like below..
[pickerControl takePicture];
I dont know what is causing it, but it crashes immediately after calling takePicture. It doesn't happen all the time.. but it crashes more often.
Please help to understand what is going wrong.
You're asking about beta software that's accessible only after consenting to a non-disclosure agreement. So I'm going to ignore the iOS 7 aspect of the question.
As to getting a crash log, if you already know which method call is crashing then you're not going to get much out of it. But what you can do is use C's signal to install exception handlers for the various exceptions you want to trace.
Upon receiving such an exception, use [NSThread callStackSymbols] to get an array of call stack symbols — a backtrace in effect. You can then hastily write that to disk and, next run, read it back and notify yourself of it accordingly. Services like Crashlytics accumulate them and post them to a server. You could just open an MFMailComposer and send them to yourself as an attachment.
Using the Crashlytics SDK or a similar product directly would allow you to get live, traced crash reports regardless of whether the build has yet been submitted to Apple and without requiring Xcode to do any parsing.
I'm fairly new at C++/Qt, and I only have some web development experience.
I'm testing a few things with Qt for learning purposes and I'm failing miserably at it. I'm pretty sure it's because the whole slot/signal thing hasn't settled in yet, so I was hoping someone could make it clearer for me.
So, I have this main program UI where I have placed a QTextEdit widget. Now I'm trying to reproduce one of those "there are changes to the document, better save it!"-warnings, and it's being displayed everytime someone tries to create a new document.
I'm trying to test for changes in the textEdit widget when the "New Document" option is triggered. I keep getting these compile errors and I don't even know what they mean! What would be the correct test condition? How can I refer to the textEdit, since it's being called somewhere else?
I'm trying something like this:
void Notepad::on_actionNew_triggered()
{
//not getting the test condition right!
if(................................) {
QMessageBox msgBox;
msgBox.setText("Warning!");
msgBox.setInformativeText("Changes were applied to this document.");
msgBox.setStandardButtons(QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Cancel);
int ret = msgBox.exec();
switch (ret) {
case QMessageBox::Discard:
// Don't Save was clicked
ui->textEdit->clear();
break;
case QMessageBox::Cancel:
msgBox.close();
break;
default:
// should never be reached
break;
}
}else{ui->textEdit->clear();}
}
I have tried searching some information about this, and I bet most of you might actually think this is pretty obvious, but I'm having real trouble understanding how to get around this.
So, you've got a few things in play here. One is when you're clicking New you need to perform a check to see if there's a document already existing that hasn't been saved, you're not far off by thinking of signal and slots for it.
So when you press New you need to send a signal to your document, if you've created a custom class this is easy as you can add a new slot dirtyDocument (for example!) which can relay the documents status back, for example by emitting another signal containing a bool flag and deal with it inside another slot. Or, in your on_actionNew_triggered slot you could ask the document object which is currently open whether it's got unsaved changes by passing a reference to the object, or maintaining a class reference to it (that's where you have something like Document *doc; in your notepad.h file).
If you're getting compile issues copy any information that doesn't have something specific to your code and paste it into Google. Odds are someone will have asked the same question, most probably on SO itself.
So, I was trying to solve this and I decided to make a slot returning a bool value whenever the textEdit has suffered changes. As I figured out, I thought of using this as a test whenever the "New action" was triggered. So, after the test, I set the bool value back to false and it's working fine:
void Notepad::on_actionNew_triggered()
{
if(Notepad::on_textEdit_textChanged()) {
~Notepad::on_textEdit_textChanged();
QMessageBox msgBox;
msgBox.setText("Warning!");
msgBox.setInformativeText("Changes were applied to this document.");
msgBox.setStandardButtons(QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Cancel);
int ret = msgBox.exec();
switch (ret) {
case QMessageBox::Discard:
// Don't Save was clicked
ui->textEdit->clear();
break;
case QMessageBox::Cancel:
msgBox.close();
break;
default:
// should never be reached
break;
}
}else{ui->textEdit->clear();}
}
bool Notepad::on_textEdit_textChanged()
{
return true;
}
I use Sample Grabber Sink in my Media session using most of code from msdn sample.
In OnProcessSample method I memcpy data to media buffer, attach it to MFSample and put this one into main process pointer. Problem is I either get memory leaking or crashes in ntdll.dll
ntdll.dll!#RtlpLowFragHeapFree#8() Unknown
SampleGrabberSink:
OnProcessSample(...)
{
MFCreateMemoryBuffer(dwSampleSize,&tmpBuff);
tmpBuff->Lock(&data,NULL,NULL);
memcpy(data,pSampleBuffer,dwSampleSize); tmpBuff->Unlock();
MFCreateSample(&tmpSample);
tmpSample->AddBuffer(tmpBuff);
while(!(*Free) && (*pSample)!=NULL)
{
Sleep(1);
}
(*Free)=false;
(*pSample)=tmpSample;
(*Free)=true;
SafeRelease(&tmpBuff);
}
in main thread
ReadSample()
{
if(pSample==NULL)
return;
while(!Free)
Sleep(1);
Free=false;
//process sample into dx surface//
SafeRelease(&pSample);
Free=true;
}
//hr checks omitted//
With this code i get that ntdll.dll error after playing few vids.
I also tried to push samples in qeue so OnProcess doesn't have to wait but then some memory havent free after video ended.
(even now it practicaly doesn't wait, Session rate is 1 and main process can read more than 60fps)
EDIT: It was thread synchronization problem. Solved by using critical section thanks to Roman R.
It is not easy to see is from the code snippet, but I suppose you are burning cycles on a streaming thread (you have your callback called on) until a global/shared variable is NULL and then you duplicate a media sample there.
You need to look at synchronization APIs and serialize access to shared variables. You don't do that and eventually either you are accessing freed memory or breaking reference count of COM object.
You need an event set externally when you are ready to accept new buffer from the callback, then the callback sees the event, enters critical section (or, reader/writer lock), does your *pSample magic there, exits from critical section and sets another event indicating availability of a buffer.
I just installed the new version of Xcode/ios6. viewDidUnload is now depreciated.
In the apple doc,
viewDidUnload [...] Deprecated in iOS 6.0. Views are no longer purged under low-memory conditions and so this method is never called.
But numbers of apps are using this callback to release their properties, like :
- (void)viewDidUnload {
[super viewDidUnload];
self.recipientButton = nil;
self.connectButton = nil;
self.infoLabel = nil;
}
This was the best practice to release your IBOutlets.
So, first question:
What is going to happen these existing apps in iOS 6? Will they leak ?
and second one:
What is the new recommended way to release an IBOutlet property ? In dealloc method ?
For the first Question:
Your ViewController will receive didReceiveMemoryWarning method callback and you can nil out the view & other components in this method
For Reference Do Check WWDC 2012 video Session on EVOLUTION OF VIEW CONTROLLER, in case you haven't (I Believe they are available only for registered developers, but not sure).
Answer to your second one.
[object release]; in dealloc. No need to assign nil to object before releasing.
I recommend you to use weak property for the IBOutlets like
#property (weak) IBOutlet UILabel * labelText;
That way you don't need to do anything in dealloc. In iOS 6, simply ViewDidUnload won't call, iOS5 or earlier it is just call when memory warning have occur.
and second one: What is the new recommended way to release an IBOutlet
property ? In dealloc method ?
What is the "old" recommended way? You must always release retained instance variables in dealloc; it has always been this way and continues to be this way.
It was just that in viewDidUnload (which is only called for low memory) you could also set your properties to nil.