11

在我目前的项目中,几个视图控制器(如vc)产生在静态NSOperationQueue上执行的NSOperation对象(如operation)。当操作正在等待或运行时,它将通过委派报告给视图控制器(operation.delegate = vc,分配未保留)。如何正确处理一个排队代理的排队nsoperation

虽然这些操作可能需要一段时间,但同时应用程序可以通过弹出导航控制器的堆栈来释放视图控制器。

到目前为止,一切都是故意的。包含静态NSOperationQueue的类有办法恢复操作,因此视图控制器不保留它们。他们只是alloc/init/autoreleased并放在队列中。

现在,这也会导致问题。在视图控制器释放后,任何对NSOperation的激进委托的调用都会导致访问冲突。据我所知,不可能检查指针上的对象是否已被释放,as stated in this question

我能想到的一个修复方法是保留操作并将操作设置为dealloc。但那是我最不喜欢的解决方案,因为它会引入很多额外的ivars /属性来跟踪。

因此,我的问题是,还有其他方法来解决这个问题,如果是的话,你能在这里画一个吗?

干杯,
EP。

SOLUTION:制定出最适合我的方法是朱利安诺的回答略有变化:

  • 实现队列管理器每个代表协议是不可行的(20个+不同的协议与50+方法),所以我保留了直接委托分配。我所做的改变是让班级进行分配。这曾经是创建请求的类(和委托),但现在它被卸载到队列管理器。

  • 队列管理器在将委托分配给操作旁边还包含辅助可变字典以跟踪委托/操作对。

  • 每个委托实例在释放时调用[QueueManager invalidateDelegate:self]方法,然后查找属于该委托的请求并将其删除。然后字典操作/委托对也被删除,以允许适当地释放该操作。

  • 最后,在KVO观察每个操作的isFinished属性后,可变字典保持清晰,以确保所有操作保留计数实际上在完成后释放。

感谢Guiliano提供了使用KVO来解决这个问题的提示!

回答

7

我建议检查您的架构和移动委托类(假设的QueueManager)管理,而不必在每个操作的代表队:

  • 创建QueueManagerDelegate是 实现方法()你需要 通知viewControllers

  • 在的QueueManager添加志愿观察员每个的NSOperation(的isFinished属性来完成这个添加操作到前队列;))

  • 在国际志愿者组织的回调调用的委托方法()你只需要当代表是=零

  • 添加无效的方法的QueueManager和调用这个方法! UIViewController中(一个或多个)的dealloc方法

    - (无效)无效 { 自>委托=零; }

的情况下,你需要对志愿刷新:Kvo programming guide

+0

+1其次。它还可以更容易地“重新连接”到vc,以防再次出现并需要响应队列(及其内容)中的更改。 – Toastor 2011-05-06 17:04:29

+0

非常有趣的方法。它将使QueueManager(确实存在)更加复杂一点,但它也将使代表团更加健壮。我会让它腌一下,但听起来像是要走的路。 – epologee 2011-05-06 17:24:59

+1

如果您需要一些示例代码,请参阅Apple文档中的FetchedImageLinker示例代码。有一个名为WatchedOperationQueue的类(或类似的东西,这里没有文档)实现了描述的行为。 – 2011-05-06 19:48:32

0

这里最好的建议是查看应用程序的架构以避免这种情况。但是,如果当前代码无法更改,请使用NSNotificationCenter。每次你的视图控制器被释放,你可以发布通知,这个通知必须通过NSOperationQueue持有者,在通知处理程序中的简单foreach循环到解除分配视图控制器的代表。应该做的伎俩。

+0

真棒建议! – epologee 2011-05-06 16:35:22

0

您还应该检查以确保任何代表(如果非零)也能够响应操作完成中的消息。您可以使用所有NSObject子类所提供的respondsToSelector函数执行此操作。

在我的项目,我已经抽象该检查到上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

+0

如果一切都正常完成,协议应该到位,无论如何,委托符合... – Toastor 2011-05-06 17:02:26

+0

不是我的问题的答案,但我只是让你知道,所有的委托协议都已到位,并具有所需的方法只要。因此不需要检查。 – epologee 2011-05-06 17:20:01