title: dealloc called on background GCD queue crashing app built with ARC
body: <p>I have a view controller that downloads an asset in a background GCD queue. I pass my downloading function a callback block to execute once the download is finished, and it always executes this block on the main thread. </p>
  
  <p>The problem occurs if my view controller is dismissed by the user before the download is finished. I suspect what's happening is, once my view controller is dismissed, the callback block is the only thing retaining a strong reference to the controller. The callback block is only retained in a background thread, so once it's released, all the objects captured in the scope of the callback block are also released, albeit in a background queue. </p>
  
  <p>This is the problem: being released in a background queue is causing dealloc to be run in that same queue, not the main queue. This, in turn, calls <code>dealloc</code> in the background and the app crashes:</p>
  
  <pre><code>2012-01-19 12:47:36.349 500px iOS[4892:12107] bool _WebTryThreadLock(bool), 0x306c10: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
  [Switching to process 16643 thread 0x4103]
  [Switching to process 16643 thread 0x4103]
  (gdb) where
  #0  0x307fd3c8 in _WebTryThreadLock ()
  #1  0x307ff1b0 in WebThreadLock ()
  #2  0x33f7865e in -[UITextView dealloc] ()
  #3  0x0005d2ce in -[GCPlaceholderTextView dealloc] (self=0x309010, _cmd=0x340ce6b8) at /Users/ash/Dropbox/500px/500px-ios/500px iOS/500px iOS/GCPlaceholderTextView.m:113
  #4  0x337cac42 in -[NSObject(NSObject) release] ()
  #5  0x33dee5f4 in -[UIView(Hierarchy) removeFromSuperview] ()
  #6  0x33e836cc in -[UIScrollView removeFromSuperview] ()
  #7  0x33f762f0 in -[UITextView removeFromSuperview] ()
  #8  0x33e01de2 in -[UIView dealloc] ()
  #9  0x337cac42 in -[NSObject(NSObject) release] ()
  #10 0x33dee5f4 in -[UIView(Hierarchy) removeFromSuperview] ()
  #11 0x33e01de2 in -[UIView dealloc] ()
  #12 0x33f437e4 in -[UIScrollView dealloc] ()
  #13 0x337cac42 in -[NSObject(NSObject) release] ()
  #14 0x33dee5f4 in -[UIView(Hierarchy) removeFromSuperview] ()
  #15 0x33e836cc in -[UIScrollView removeFromSuperview] ()
  #16 0x33e01de2 in -[UIView dealloc] ()
  #17 0x337cac42 in -[NSObject(NSObject) release] ()
  #18 0x33dee5f4 in -[UIView(Hierarchy) removeFromSuperview] ()
  #19 0x33e01de2 in -[UIView dealloc] ()
  #20 0x337cac42 in -[NSObject(NSObject) release] ()
  #21 0x33e5a00e in -[UIViewController dealloc] ()
  #22 0x00035f16 in -[PXPhotoViewController dealloc] (self=0x5158d0, _cmd=0x340ce6b8) at /Users/ash/Dropbox/500px/500px-ios/500px iOS/500px iOS/PXPhotoViewController.m:118
  #23 0x337cac42 in -[NSObject(NSObject) release] ()
  #24 0x337e5046 in sendRelease ()
  #25 0x331fc92e in _Block_object_dispose ()
  #26 0x0003c33a in __destroy_helper_block_ () at /Users/ash/Dropbox/500px/500px-ios/500px iOS/500px iOS/PXPhotoViewController.m:878
  #27 0x331fc88e in _Block_release ()
  #28 0x331fc91c in _Block_object_dispose ()
  #29 0x000c8d32 in __destroy_helper_block_ () at /Users/ash/Dropbox/500px/500px-ios/500px iOS/500px iOS/PXPhotoFetcher.m:557
  #30 0x331fc88e in _Block_release ()
  #31 0x35eec8ec in _dispatch_call_block_and_release ()
  #32 0x35ee2de2 in _dispatch_queue_drain ()
  #33 0x35ee2f32 in _dispatch_queue_invoke ()
  #34 0x35ee24f2 in _dispatch_worker_thread2 ()
  #35 0x34ecb590 in _pthread_wqthread ()
  #36 0x34ecbbc4 in start_wqthread ()
  </code></pre>
  
  <p>The code I execute on the main thread looks like this:</p>
  
  <pre><code>[[PXPhotoFetcher sharedPXPhotoFetcher] fetchPhotoDetailsWithPriority:PhotoRequestLowPriority 
      withCallback:^(PXPhotoModel *thePhotoModel) {
          // a callback function which captures self in its scope
      } forModel:model];
  </code></pre>
  
  <p>I'm building for 4.3, so if I use an __unsafe_unretained reference to self in the callback block, this will fix my current problem but introduce the new problem of having a dangling pointer. </p>
  
  <p>What do you recommend for architecting a solution for this? Other workarounds included <a href="https://stackoverflow.com/questions/945082/uiwebview-in-multithread-viewcontroller/4299021#4299021">overriding <code>release</code></a> so that it was always invoked on the main thread, but this obviously isn't going to work in the ARC environment. </p>
  
  <p>This seems like it should be a far more common problem with ARC and GCD, but I can't find anything online. Is it just because I'm targeting &lt; iOS 5 and can't use weak references?</p>