UIViewController があり、そのコントローラーで、URL ソースから画像を取得しています。画像は別のスレッドでフェッチされ、その後メイン スレッドでユーザー インターフェイスが更新されます。このコントローラーは、表示されなくなったコントローラーを解放するために実装された UIScrollView 親のページとして表示されます。
UIViewController が解放される前にスレッドがコンテンツのフェッチを終了すると、すべて正常に動作しますが、スレッドが終了する前にユーザーが別のページにスクロールすると、コントローラーが解放され、コントローラーへの唯一のハンドルがコントローラーの releaseCount を作成するスレッドによって所有されます。これで、スレッドが NSAutoreleasePool を排出するとすぐに、releaseCount が 0 になるため、コントローラーが解放されます。この時点で、アプリケーションがクラッシュし、次のエラー メッセージが表示されます。
bool _WebTryThreadLock(bool), 0x4d99c60: メイン スレッドまたは Web スレッド以外のスレッドから Web ロックを取得しようとしました。これは、セカンダリ スレッドから UIKit を呼び出した結果である可能性があります。現在クラッシュ中...
バックトレースは、[super dealloc] の呼び出しでアプリケーションがクラッシュしたことを示しています。これは、プールがドレインされたときにスレッドによって dealloc 関数がトリガーされたに違いないため、完全に理にかなっています。私の質問は、このエラーを克服し、メモリをリークすることなくコントローラーを解放するにはどうすればよいですか?
私が試した解決策の 1 つは、プールが空になる前に [自己保持] を呼び出して、retainCount がゼロにならないようにし、次のコードを使用してメイン スレッドでコントローラーを解放することでした。
[self performSelectorOnMainThread:@selector(autorelease)
withObject:nil waitUntilDone:NO];
残念ながら、これはうまくいきませんでした。以下は、スレッドで実行される関数です。
- (void)thread_fetchContent {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSURL *imgURL = [NSURL URLWithString:@"http://www.domain.com/image.png"];
// UIImage *imgHotspot is declared as private - The image is retained
// here and released as soon as it is assigned to UIImageView
imgHotspot = [[[UIImage alloc] initWithData:
[NSData dataWithContentsOfURL: imgURL]] retain];
if ([self retainCount] == 1) {
[self retain]; // increment retain count ~ workaround
[pool drain]; // drain pool
// this doesn't work - i get the same error
[self performSelectorOnMainThread:@selector(autorelease)
withObject:nil waitUntilDone:NO];
}
else {
// show fetched image on the main thread - this works fine!
[self performSelectorOnMainThread:@selector(showImage)
withObject:nil waitUntilDone:NO];
[pool drain];
}
}
助けてください!前もって感謝します。