{"comment":{"created_at":"2011-10-10T17:54:35Z","body":"There are three solutions.\r\n\r\n1. Within the block that is created to be assigned to `completionBlock`, use a `__block` variable like so:\r\n\r\n        __block AFImageRequestOperation *blockOperation = [operation retain];\r\n        operation.completionBlock = ^{\r\n            if ([blockOperation isCancelled]) {\r\n            ...\r\n            [blockOperation release];\r\n        };\r\n\r\n    This is kinda messy since you have to be careful not to capture `operation` within the block. Also, the memory management is nasty.\r\n\r\n2. Add a parameter of type `NSOperation *` to the completion block (naming `completionBlock` something else, of course, so it doesn't conflict with the built-in property). Then use that parameter within the block. This has the advantage that a block can be constructed before the operation, if you fancy it.\r\n\r\n3. Just break the retain cycle manually, [as recommended here](http://lists.apple.com/archives/cocoa-dev/2010/Sep/msg00903.html). You can call `[operation setCompletionBlock:nil]` at the end of the completion block you create. Or, `AFURLRequestOperation` can set its own `completionBlock` to `nil` after calling it.\r\n\r\nI vote for option 3.","updated_at":"2011-10-10T17:54:35Z","url":"https://api.github.com/repos/gowalla/AFNetworking/issues/comments/2350174","id":2350174,"user":{"avatar_url":"https://secure.gravatar.com/avatar/072abdb5a6787505e87044eda654a49b?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","url":"https://api.github.com/users/adamjernst","id":97944,"login":"adamjernst"}},"action":"created","issue":{"number":56,"created_at":"2011-09-29T23:35:11Z","pull_request":{"diff_url":null,"patch_url":null,"html_url":null},"body":"AFNetworking is growing up so it's time to consider a very nasty, sticky problem with blocks, one which Apple ominously labels [The Deallocation Problem](http://developer.apple.com/library/ios/#technotes/tn2109/_index.html#//apple_ref/doc/uid/DTS40010274-CH1-SUBSECTION11).\r\n\r\n`UIViewController` needs to be released on the main thread. `AFHTTPRequestOperation` will almost always capture a reference to a `UIViewController` in its completion block (as long as you reference `self` or any instance variable).\r\n\r\nIf all other references to your `UIViewController` are first released from the main thread (e.g., it is popped from the navigation stack), and then the operation completes, the view controller is released on a background thread. This will instantly crash as `UIViewController` fails an assertion if `dealloc`'d on a background thread.\r\n\r\nThis happens whether you put the operation in an `NSOperationQueue` (in which case the operation is released on the background thread of the queue) or if you call `-start` on the main thread to use it as a concurrent operation (in which case the operation is released on `networkRequestThread`; the last retaining reference to it is the `NSURLConnection` running there which retains its delegate, the operation).\r\n\r\nThis is not hard to reproduce. Create a long-running operation (i.e., response takes more than a few seconds due to network or server latency). Push and immediately pop a view controller that creates that operation and has a completion handler referencing `self`.\r\n\r\nThe hard part is how to work around this—both in classic memory management and now ARC. Apple's recommended fix involves a special `NSOperationQueue` subclass with special KVO wrapper methods, something which I dismiss immediately.\r\n\r\nAs a consumer of the library, here's the inelegant solution I take:\r\n\r\n    __block id blockSelf = [self retain];\r\n    [myOperationQueue addOperation:[AFHTTPRequestOperation operationWithRequest:... completion:^(...){\r\n        dispatch_async(dispatch_get_main_queue(), ^{\r\n            // Handle response without referencing instance variables.\r\n            // Use blockSelf instead of self.\r\n            [blockSelf release];\r\n        });\r\n    }]];\r\n\r\nSide note about ARC: solving it under ARC is even trickier since `__block` references now do retain their referent. (See \"Use Lifetime Qualifiers to Avoid Strong Reference Cycles\".) I believe setting the reference to `nil` within the `dispatch_async` to the main queue would safely release it on the main thread, but I'm not certain. Creating a `__weak` reference to self is an intriguing way to fix it. However, you'd still have to be careful not to refer to any instance variables and it only works on iOS 5+.\r\n\r\n## The Question Is...\r\nWhat can AFNetworking do to prevent this situation? Should it try at all, or is this just something library consumers need to be aware of and handle themselves?\r\n\r\nI think it would be nice if AFNetworking did prevent this situation, if it's possible without too much trouble. `blockSelf` makes my skin crawl and Apple's solution is even uglier.\r\n\r\nThe solution I came up with is to have `AFHTTPRequestOperation` dispatch a block to the main queue to release the `completion` property there. I haven't implemented or tested this yet. Before I sketch out the solution in detail, I'll pause here and let you fill in your thoughts on the problem and if this seems like the right direction.","comments":6,"title":"\"The Deallocation Problem\"","updated_at":"2011-10-10T17:54:35Z","url":"https://api.github.com/repos/gowalla/AFNetworking/issues/56","id":1781496,"assignee":null,"milestone":null,"closed_at":null,"user":{"avatar_url":"https://secure.gravatar.com/avatar/072abdb5a6787505e87044eda654a49b?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","url":"https://api.github.com/users/adamjernst","id":97944,"login":"adamjernst"},"html_url":"https://github.com/gowalla/AFNetworking/issues/56","labels":[],"state":"open"},"legacy":{"issue_id":1781496,"comment_id":2350174}}