私はかなり標準的な設定をしています。ユーザーインタラクションを処理するUIViewControllerと、UIControllerが表示されたときに実際の作業を行うやや長時間実行されるNSThreadがあります。私が抱えていた問題の1つは、NSThreadをキャンセルしたいときです。標準のNSThreadセマンティクスは問題ありません。スレッドを終了し、それ自体をクリーンアップして(UIViewControllerへの参照を解放するように)、UIViewControllerをポップします。したがって、私のコードは次のようになります。
NSThreadセレクターの場合:
-(void) nsThreadWork
{
// do work here
@synchronized(self)
{
[nsThreadInstance release];
nsThreadInstance = nil;
}
}
スレッドを生成するUIViewControllerでは、次のようになります。
-(void) startThread
{
nsThreadInstance = [[NSThread alloc] initWithTarget:self
selector:@(nsThreadWork) ...];
[nsThreadInstance start];
[nsThreadInstance release];
}
そしてキャンセルしたい場合:
// assume that this will be retried until we can execute this successfully.
-(void) cancelBackgroundOpAndPopViewController
{
@synchronized(self)
{
if (nsThreadInstance == nil)
{
[self popViewController];
}
}
}
しかし、これが正しいかどうかは疑問です。問題は、UI要素はメインスレッドからのみ操作できることです。NSThreadが終了する前にViewControllerをポップすると、NSThreadが終了してView Controllerを解放します。これは、NSThreadのコンテキストから割り当てが解除され、アサートが発生することを意味します。上記のコードではすべてが正しく機能しているように見えますが、runloopがNSThreadの割り当てを解除するタイミングがわかりません。誰かが洞察を提供できますか?