6

我有一个NSOperations用于管理对 Web API 的服务调用的应用程序(这些调用基于Jon Wight 的 touchcode 中的 CURLOperation)。

当地图视图的中心发生显着变化时,有一个下载地图位置的调用;因为这些可以很快堆积起来,如果你移动地图,我会尝试积极取消过时的操作。它在 4.0 上运行良好。

但是,在 3.1 上,似乎在某些情况下操作队列将保留已取消(和已释放)的操作,当它到达它们应该在队列中的位置时会导致崩溃。

这是一个插图。

我从队列中一个相对重量级的服务调用开始:

  1. MyLongRunningOp 0x1

用户导航到地图。队列现在看起来像这样:

  1. MyLongRunningOp 0x1
  2. MyMapOp 0x2

他们移动地图,取消 MyMapOp 0x2 并添加 MyMapOp 0x3:

  1. MyLongRunningOp 0x1
  2. MyMapOp 0x3

MyMapOp 0x2现在已释放,因为它已从队列中删除。现在MyLongRunningOp 0x1结束。在设置 isFinished 键的 KVO 回调中MyLongRunningOp,我看到操作队列处理通知并尝试将其添加MyMapOp 0x2到一些NSArray. 自然,NSZombies启用后,

[MyMapOp retain]: message sent to deallocated instance 0x2

似乎它以NSOperationQueue某种方式挂在指向取消/释放操作的指针上,并在先前的操作完成后尝试激活它。

我无法在 4.0 上重现这种行为,所以我相信这是 3.1 的错误。

我在解决它时遇到了很多麻烦——据我所知,唯一的解决方法是永远不要取消我的操作,这会在网络变得不稳定时造成次优体验。

有没有其他人经历过这个?有任何想法吗?

4

1 回答 1

1

我在 NSOperations 上使用 KVO 时遇到了(我认为是)类似的问题。

只是看了你的描述,我的第一反应是检查操作队列的规则。是否有可能一旦您将它交给队列,队列应该承担所有权,因此您不应该手动释放它?(不确定你是不是)。

根据我的个人经验,也许它会有所帮助或没有:

1) 当你取消一个操作时,从中移除 KVO 观察者。我曾经发生过这种情况,当任何一方被删除时,KVO 都不会取消链接。

2) 请注意,KVO 回调与 NSOperation 在同一线程中运行。因此,在您开始操作和 KVO 回调之间,对象可能会超出范围。

如果您发布代码,我可能会给您更多帮助。希望以上内容对你有用!

于 2011-05-10T15:47:23.847 回答