如何正确处理排队的nsoperation的解除分配代理

epo*_*gee 11 exc-bad-access delegation objective-c nsoperation nsoperationqueue

在我当前的项目中,几个视图控制器(如vc)生成operation在静态NSOperationQueue上执行的NSOperation对象(如).当操作正在等待或运行时,它将通过委托(报告operation.delegate = vc未保留)向视图控制器报告.

这些操作可能需要一段时间,同时应用程序可以取消分配视图控制器(通过弹出导航控制器的堆栈).

到目前为止,一切都是故意的.包含静态NSOperationQueue的类有一种方法可以返回操作,因此视图控制器不会保留它们.它们只是alloc/init/autoreleased并放入队列.

现在这也导致了这个问题.在视图控制器解除分配后,对NSOperation的激烈委托的任何调用都将导致错误的访问冲突.根据我的理解,无法检查指针上的对象是否已被解除分配,如本问题所述.

我能想到的一个修复是保留操作并在dealloc上将operation.delegate设置为nil.但这是我最不受欢迎的解决方案,因为它会引入许多额外的ivars /属性来跟踪.

因此,我的问题是,有没有其他方法可以解决这个问题,如果是这样,你能在这里草拟一个吗?

干杯,
EP.

解决方案:对我来说最好的方法是对Guiliano的回答略有不同:

  • 在队列管理器中实现每个委托协议是不可行的(20多种不同的协议,使用50多种方法),因此我保留了直接委托分配.我改变的是进行分配呼叫的班级.这曾经是创建请求的类(和委托),但现在它被卸载到队列管理器.

  • 除了将委托分配给操作之外,队列管理器还拥有辅助可变字典以跟踪委托/操作对.

  • 每个委托实例都会调用一个[QueueManager invalidateDelegate:self]deallocation方法,然后查找属于该委托的请求并将其取消.然后还删除字典操作/委托对以允许适当地重新分配操作.

  • 最后,当KVO观察isFinished每个操作的属性时,可变dict保持清洁,以确保所有操作保留计数在它们完成后实际解除分配.

感谢Guiliano提供使用KVO破解这一点的提示!

Giu*_*lea 7

我建议您检查您的体系结构并将委托移动到管理队列的类(假设QueueManager),而不是在每个操作中都有一个委托:

  • 创建一个QueueManagerDelegate,实现通知viewControllers所需的方法

  • 在QueueManager中为每个NSOperation的isFinished属性添加一个KVO观察者(在将操作添加到队列之前执行此操作;))

  • 在KVO的回调中,只有当委托是!= nil时,才需要委托方法

  • 向QueueManager添加一个invalidate方法,并在UIViewController的dealloc方法中调用此方法

    - (void)invalidate {self-> delegate = nil; }

如果您需要刷新KVO:Kvo编程指南