2
votes

I am doing an application which downloads image from server and displays it on a view. I am using delegate for that. Once the image is finished loading a delegate sends message to the view to show the image.

The above scenario is working fine. But if I move out from that particular view to any other view, when the image loading is finished the delegate tries to send message and causes an error.

I tried setting the

imageFetcher.delegate=nil;

in view didUnload. Also before calling the delegate method in download class I check for delegate is nil.

But i can see that the delegate object is not nil.

if(delegate!=nil)
{
  [delegate imagefetcherView:self didLoadImage:image];
}

How can I fix this error?

Thanks

4
Are you sure viewDidUnload calling is your code??? I think it could not called it depreciated method in latest ios verion see this doc developer.apple.com/library/ios/documentation/uikit/reference/…Tirth

4 Answers

7
votes

Do not rely viewDidUnload to do any cleanup. That's only called in iOS versions prior to iOS 6, and only when the view is unloaded due to memory pressure (but not when you just dismiss/pop the view).

Set your delegate to nil in the dealloc method or viewDidDisappear or wherever is appropriate.

Two caveats relevant to picking which method you'll nil the delegate:

  1. Be aware that viewWillDisappear and viewDidDisappear will also be called if you push/present another view controller, even if the current one has not been yet been dismissed. Only rely upon these disappear-related methods if the view controller in question does not ever push/present another view controller.

  2. If employing the dealloc technique, note that this only works if the delegate is a weak property of the image fetcher class (and delegates generally should be weak). If the delegate was a strong or retain property, that will prevent the view controller's dealloc from ever getting called.

By the way, I gather that you are letting the image fetch continue, even though the view controller has been dismissed. You might want to not only nil the delegate, but cancel the request, too. It depends upon whether (a) you're using a fetch that even permits a cancellation (e.g. a NSURLConnectionDataDelegate approach or a AFNetworking operation) and, if so, (b) whether you want it to cancel or not. It's easy, though, to tie up precious network resources (esp if on a slow cellular connection) letting requests continue even if the user doesn't need it anymore. It depends upon the particulars of your app.

Regardless, do not rely upon viewDidUnload.

3
votes

viewDidUnload isnt called in iOS 6+.

you should use this

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
     imageFetcher.delegate=nil;
}
0
votes

You still can have a dealloc call in your class but it should not call [super dealloc]. If you add it you can set up a breakpoint here and see from where its gets its retain count to 0. Or use Instruments to track retain/release cycle of your controller.

0
votes

I would implement a separate cache to temporarily store the picture in care view controller is deallocated but the picture can be used once again, e.g. if the user gets back to the same page.

In that case you would have a long-lived cache object as a delegate. View controllers can, for example, subscribe to receive key-value notifications about incoming pictures when those view controllers become visible (just don't forget to unsubscribe from KVO in viewWillDisappear).

If your controller is invisible but likely to be shown again you'll have the picture in cache (to be dropped if low memory); of course you can also check in the cache if your picture is never likely to be shown again and drop the picture.