バックグラウンドGCDキューにアセットをダウンロードするビューコントローラがあります。私は、ダウンロードが完了したら、ダウンロード機能をコールバックブロックに渡し、メインブロック上でこのブロックを実行します。ダウンロードが完了する前に、私のビューコントローラがユーザによって却下された場合deallocが背景で呼び出されましたGCDのキューがクラッシュするARCで作成されたアプリケーション
問題が発生します。私は何が起こっているのだろうと思う、一度私のビューコントローラが却下され、コールバックブロックは、コントローラへの強い参照を保持する唯一のものです。コールバックブロックはバックグラウンドスレッドにのみ保持されるため、リリースされると、コールバックブロックのスコープでキャプチャされたすべてのオブジェクトもバックグラウンドキューに存在しますが、解放されます。
これは問題です:にdeallocが同じキューではなく、メインキューで実行することが原因となっているバックグラウンドキューにリリースされています。これは、順番に、背景とアプリのクラッシュにdealloc
を呼び出します。
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()
私はメインスレッドで実行するコードは次のようになります。
[[PXPhotoFetcher sharedPXPhotoFetcher] fetchPhotoDetailsWithPriority:PhotoRequestLowPriority
withCallback:^(PXPhotoModel *thePhotoModel) {
// a callback function which captures self in its scope
} forModel:model];
ので、もし私が、4.3用に構築しています私は__unsafe_unretainedコールバックブロックの自己参照を使用して、これは私の現在の問題を修正しますが、ぶら下がりポインタを持つ新しい問題を導入します。
このためのソリューションの設計には、どのような方法をお勧めしますか?その他の回避策にはoverriding release
が含まれていたため、メインスレッドで常に呼び出されていましたが、これは明らかにARC環境では機能しません。
それはARCとGCDとはるかに多くの共通の問題でなければなりませんようにこれはそうですが、私は、オンラインで何かを見つけることができません。それはちょうど私が< iOS 5をターゲットに設定しているため弱い参照を使用できないのでしょうか?
弱い参照が好きな人は、http://mikeash.com/pyblog/introducing-mazeroingweakref.htmlを参照してください。 – tapi
少し醜いですが、それは巧妙なトリックです。私はより良い答えを持っていればいいと思う。 –
ええ、私はMike Ashのソリューションを見ていましたが、私は短期間でiOS 4.3しかサポートしていないので、ちょっと試してみます。 –