I have a UIWebView named wView. I want to use webViewDidFinishLoad: in my class, so I am setting the class as the delegate for wView by using this line:
wView.delegate = self;
Everything loads properly, but when I close the UIWebView, the App crashes. If I comment out the wView.delegate = self, it works and does not crash, but then I can't use webViewDidFinishLoad: - any ideas? Do I need to release something?
The UIWebView Reference says:
Important: Before releasing an instance of UIWebView for which you have set a delegate, you must first set its delegate property to nil. This can be done, for example, in your dealloc method.
Ensure to set the delegate to nil (wView.delegate = nil). This will prevent webview from trying to access and call methods on a dealloc'd view controller, which would result in a crash.
Related
I have a NSDictionary, storing value by parsing. I am allocating and storing value in -viewDidLoad. And accessing the values in -viewWillAppear. It works perfectly fine.
Then, I have UIPageControl with UIScrollView. While scrolling the UIScrollView, again I am accessing the same dictionary, it crashes saying
[CFString respondToSelector:]: send to deallocated....
- (void) viewDidLoad {
[super viewDidLoad];
scoresDict = [[NSDictionary alloc] initWithDictionary:[scoreObj scores]];
}
- (void)loadScrollViewWithPage:(int)page {
if (page < 0)
return;
if (page >= kNumberOfPages)
return;
NSLog(#“scoresDict %#”,scoresDict);
}
I tried using retain in the same function, it didn’t work out. And copy, it also didn’t work. Any help would be appreciated. Thanks!
You don't say so, but it looks like all of these methods are being called from an instance of your custom UIViewController or UIScrollViewController subclass.
The most likely problem is that this instance itself isn't being retained.
When you first load the view from the nib, both -viewDidLoad and -viewWillAppear are called. It's possible, however, that garbage collection is happening in between those calls and your call to -loadScrollViewWithPage, and that no object has any connection to the view controller instance itself.
If that's the case, using copy or retain on the scoresDict won't solve the problem. You need to make sure that you are copying or retaining the view controller instance itself. Figure out what object needs to be retaining your view controller and make sure it is being retained.
A quick way to test whether this is the problem or not: create a "myViewController" property in your application delegate. In viewDidLoad, add a line:
[[[UIApplication sharedApplication] delegate] setMyViewController:self];
If this fixes your problem, it means the problem was the view controller getting released. That doesn't mean this is your best solution, though--it's just a diagnostic. You need to figure out what should be retaining your view controller and make sure it does so.
I write iOS app and use imageStore library to lazy load images and cache them in memory. (https://github.com/psychs/imagestore)
On ViewController I create imagestore instance:
imageStore = [ImageStore new];
imageStore.delegate = self;
When image loaded successfuly, imagestore call delegate method
- (void)imageStoreDidGetNewImage:(ImageStore*)sender url:(NSString*)url
that doing reloadData on tableview to redraw cells.
All works good. But there is the problem: if ViewController didUnload (go back in navigation controller) and image loaded, application finish with crash, because imagestore call method of unloaded ViewController.
I try to do following:
1) in ViewController I place this code in viewDidUnload section:
imageStore.delegate = nil;
imageStore = nil;
2) In imageStore I added checking for nil:
if(delegate != nil) {
...call delegate method
}
It works, but periodically app crash anyway.
Try putting this code on dealloc section.
imageStore.delegate = nil;
imageStore = nil;
In the same way the if clause is not necessary because any call to an nil object is ignored by the application, so if you have something like this:
id delegate = nil;
[delegate callAnyMethod];
has no effect in your application behavior, in other hand if the call of the method delegate is optional you should asure that delegate responds to selector, something like this should do the trick:
if([delegate conformsToProtocol:#protocol(yourProtocolName)] && [delegate respondsToSelector:#selector(imageStoreDidGetNewImage:url:)]) {
[delegate imageStoreDidGetNewImage:imageStore url:url];
}
Cheers!
It works, but periodically app crash anyway.
That's a contradiction. There are two possibilities:
Your fix worked, and the app is crashing for some other reason.
Your fix did not work, the app continues to crash for the same reason it was crashing before.
It's hard to know what's wrong without knowing which of these two possibilities is in fact happening. Look at the error message and the evidence from the crash, such as the stack crawl. Why is the app crashing? Does it try to dereference the delegate property somewhere without checking it first? Does it depend on the delegate doing something, so that if the delegate no longer exists that thing doesn't get done and that in turn leads to a crash? These are the kinds of things I'd look for, but again the most important thing is to start with the evidence you have and follow your nose.
I have run into a real hard one here.
My class is self-created (a + (void) start;-method) which is sent a delegate.
I need to send the delegate a few messages through delegate-selectors. To check if the delegate was released, I have tried if (delegate == nil/NULL), but even if it really is released, it still says it wasn't.
How do I go around to fix this? (delegate is assigned to an id)
This is how my app is built up:
AppDelegate
> NavController
>> TableView
>>> Post
>>>> GetData
GetData is the self-created class. Post is the delegate of GetData, and is released by TableView/NavController. After releasing Post, it is also set to nil.
In other words, GetData does not release it's delegate!
Deallocating the content of a pointer does not set the pointer to NULL automatically. You need to do it explicitly, e.g.
[delegate release];
delegate = nil;
You can't check if an object was released. Another object could've come along and occupied the same memory space, becoming indistinguishable with the original object.
The user of a class with a delegate is responsible for setting the delegate to nil when the delegate object is released. It's not detectable by the object itself.
I have a MKMapView. Sometimes after my view controller is dismissed, I'll get a EXC_BAD_ACCESS.
I turned on NSSZombies and it looks like the MKMapView's delegate — my view controller! — is being called, despite both the MKMapView and UIViewController subclass being freed. I've checked, and my memory management is correct.
What's going on?
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.
OK, this is the confirmation of the answer. It's from the Apple doc, but it's missing from MKMapView. It's only found under the documentation for its delegate protocol:
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.
NOTE: This also applies to UIWebView.
I set the MapView's delegate pointer to nil in the delegate's dealloc method, and our crashes seem to have been eliminated.
Setting the map view's delegate to nil didn't work for me. However, setting showsUserLocation=NO on the delegate worked by making sure no location updates are received.
The problem, in my case, was that first time I launched app I don't press "allow" when prompting for location authorization (accidentally!!).
Uninstalling app and re-installing it, when prompt appear I allow the authorizations and no more crash!
I have created a nib file and added a UIWebView. i created an IBOutlet and attached web view with that outlet. till here everything is fine . now when i set the delegate of that webview to self in ViewDidLoad, and implement two of its delegate methods. the application crashes, i m not writing anything in the methods , i have just implemented and the application is crashing ....
what could b the problem ?
is there any problem ???
There is a problem if one of the delegate methods is
– webView:shouldStartLoadWithRequest:navigationType:
Indeed, this method returns a BOOL (YES if the web view should begin loading content; otherwise, NO). Therefore, since you are not writing any code inside the method, this may cause a problem. Try inserting in this method the statement
return YES;
The other delegate methods return void, so these should not be the cause of the problem.