首先(由于这个问题与内存管理有关),我不得不说我在 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 保持活动状态,因为该数组是唯一引用该进程的对象。当在完成块上我从数组中删除进程时,我认为进程会立即解除锁定。然后,由于进程包含块本身,块在它仍在运行时也会被解除锁定!
我预计这会导致问题,但我已经测试了这段代码,并且该块运行良好,直到结束。现在,有两种选择:要么我的推理是错误的,而这段代码是完全安全的,要么我是对的(或至少部分是对的),但这是不安全的,因为它只在某些时候有效。
基本上,我的问题是:这种回调块的方法安全吗?如果没有,你能提出一些不同的建议吗?