如何正确处理已排队的nsoperation的释放委托

|| 在我当前的项目中,几个视图控制器(例如
vc
)产生了在静态NSOperationQueue上执行的NSOperation对象(例如
operation
)。当操作正在等待或运行时,它将通过委派(
operation.delegate = vc
,未保留分配)报告给视图控制器。 这些操作可能要花一些时间,与此同时,应用程序可以取消分配视图控制器(通过将它们从导航控制器的堆栈中弹出)。 到目前为止,一切都是故意的。包含静态NSOperationQueue的类具有返回操作的方法,因此视图控制器不会保留它们。它们只是alloc / init / autoreleased并放在队列中。 现在,这也导致了问题。视图控制器取消分配后,对NSOperation活跃代理的任何调用都将导致严重的访问冲突。据我了解,无法检查指针处的对象是否已被释放,如本问题所述。 我能想到的一个解决方法是保留该操作并将dealloc上的operation.delegate设置为nil。但这将是我最不受欢迎的修复方法,因为它会引入很多额外的ivars /属性来跟踪。 因此,我的问题是,是否还有其他方法可以解决此问题,如果可以,您可以在这里画一个草图吗? 干杯, EP。 解决方案:最适合我的方法与Guiliano的回答略有不同: 在队列管理器中实现每个委托协议都是不可行的(20多种不同的协议和50多种方法),因此我保留了直接委托分配。我所做的更改是进行分配呼叫的班级。这曾经是创建请求的类(和委托),但现在已将其卸载到队列管理器。 队列管理器除了将委托分配给操作之外,还拥有一个辅助可变字典来跟踪委托/操作对。 每个委托实例都会在释放时调用
[QueueManager invalidateDelegate:self]
方法,该方法然后查找属于委托的请求并将其无效。然后,字典操作/委托对也将被删除,以允许正确地重新分配操作。 最后,在KVO观察每个操作的
isFinished
属性时,可变dict保持干净,以确保所有操作保留的计数在完成后实际上会释放。 感谢Guiliano提供了使用KVO破解它的提示!     
已邀请:
我建议您检查一下您的体系结构,然后将委托移至管理队列的类(假设QueueManager),而不要在每个操作中都有委托: 创建一个QueueManagerDelegate 实现您需要的方法 通知viewControllers 在QueueManager中,为每个NSOperation的isFinished属性添加一个KVO观察者(在将操作添加到队列之前执行此操作;) 在KVO的回调中调用委托方法,仅当委托为!= nil时才需要 将无效方法添加到QueueManager并在UIViewController的dealloc方法中调用此方法   -(无效)无效   {       self-> delegate = nil;   } 如果您需要更新KVO:Kvo编程指南     
最好的建议是检查应用程序的体系结构,以避免出现这种情况。但是,如果无法修改当前代码,可以使用NSNotificationCenter。每当您的视图控制器被释放时,您都可以发布通知,该通知必须由NSOperationQueue持有人捕获,通知处理程序中的foreach循环很简单,以使未分配视图控制器的委托无效。应该做到的。     
您还应该检查以确保所有委托(如果非零)也能够响应操作完成后的消息。您可以使用所有NSObject子类都具有的“ 5”功能来执行此操作。 在我的项目中,我已将此检查抽象为NSObject上的一个类别,该类别使我可以安全地调用带有任意数量的对象参数的委托:
- (void) dispatchSelector:(SEL)selector 
           target:(id)target 
          objects:(NSArray*)objects 
     onMainThread:(BOOL)onMainThread {

if(target && [target respondsToSelector:selector]) { // Do your delegate calls here as you please } }

您可以在此处看到完整的示例:https://github.com/chaione/ChaiOneUtils/blob/master/Categories/NSObject-Dispatch.m     

要回复问题请先登录注册