まず第一に (この質問はメモリ管理に関係しているため)、私は ARC で実行していると言わざるを得ません。
MyProcess オブジェクトの配列を含むオブジェクト (MyObject) があります。MyObject は、特定の時点で、新しい MyProcess を作成し、それを配列に追加し、ブロックの形式で完了ハンドラーを提供し、プロセスに開始を指示します。
MyProcess* newProcess = [MyProcess new];
[allProcessesArray addObject: newProcess];
newProcess.completionBlock = ^(MyProcess* process){
[allProcessesArray removeObject: process];
// Other things are done here
};
[newProcess start];
ここで、MyProcess 側では、start が呼び出されると、MyProcess は内部的に threadedStart (バックグラウンド スレッドで実行される) を呼び出します。これは作業を実行し、終了時にブロックを呼び出します。
- (void)threadedStart
{
// Do something
dispatch_async(dispatch_get_main_queue(), ^{ self.completionBlock(self); });
}
完了ブロックは、次のように MyProcess のインターフェイスでプロパティとして定義されます。
typedef void(^MyCallbackBlock)(MyProcess* process);
@property (strong) MyCallbackBlock completionBlock;
現在、MyProcess は allProcessesArray によって存続期間中のみ維持されます。これは、その配列がプロセスへの参照を持つ唯一のオブジェクトであるためです。完了ブロックで配列からプロセスを削除すると、プロセスはすぐにロック解除されると思います。次に、プロセスにはブロック自体が含まれているため、ブロックがまだ実行されている間にブロックもロック解除されます。
これにより問題が発生することが予想されますが、このコードをテストしたところ、ブロックは最後まで問題なく動作しました。ここで、2 つの選択肢があります。私の推論が間違っていて、このコードは完全に安全であるか、または私が正しい (または少なくとも部分的に正しい) が、時々しか機能しないため、これは安全ではありません。
基本的に、私の質問は: コールバック ブロックへのこのアプローチは安全ですか? そうでない場合は、別のことを提案できますか?