What's retaining the request? (The operation queue, perhaps? Who knows?)
In general, the "fire-and-forget-and-give-me-a-callback" method you seem to be proposing is a bad idea. If nothing is retaining the VC apart from the request, then (unless your app structure is a bit silly) the VC will never get to do anything with the data it receives, so there's no reason for it to continue.
It also feels wrong: Does the request own the VC, or does the VC own the request? I'd expect the latter, so the VC should also retain the request.
There are a couple of exceptions:
- CAAnimation.delegate is retained, presumably because the animation is going to complete at some point (I'm not sure what happens if it's a repeating animation). The same may be true of UIKit's animation delegate
- NSTimer retains its target, probably because NSInvocation does. (I wrote a "weak timer" class to work around this.)
- CADisplayLink retains its target, presumably to be like NSTimer.
For these cases, I often work around it with a "weak proxy" class which doesn't retain its target (and I wrote a "weak timer" wrappers around NSTimer/CADisplayLink to make this a bit easier.)
What you're supposed to do is keep track of the requests that you've initiated and in dealloc, do something like
request.delegate = nil;
[request cancel];
self.request = nil;
Similarly, you're supposed to unregister for notifications/actions/KVO callbacks at the appropriate time. There's an exception:
- If you're sure that it won't send you a callback after you release it, you don't need to bother, so text field delegates and button action/targets don't need to be cleared.
There are exceptions to the exception:
- UIWebView (at least in older OSes) are also retained by something else, possibly something to do with the web thread. It can crash if the VC disappears while the web view is still loading.
- UIScrollView scrolling callbacks also cause the view to be retained past the lifetime of the VC. You can test this by e.g. holding "Done" and starting a flick as you release "Done".