【问题标题】:Calling -(void) cancelAllOperations on NSoperationQueue is not setting the isCancelled property of NSOperation that is present inside the Queue在 NSoperationQueue 上调用 -(void) cancelAllOperations 不会设置队列中存在的 NSOperation 的 isCancelled 属性
【发布时间】:2013-05-05 15:53:16
【问题描述】:

我遇到了与 NSoperationQueue 相关的问题。 在我的代码中:

-(void) viewDidLoad
{
    //Initialisation of queue and operation.
    //adding operation to queue
    [self.operationQueue addOperation:op];

}

 -(void) viewWillDisappear:(BOOL)animated 
{
   [super viewWillDisappear:animated];
   [self.operationQueue cancelAllOperations];
}

所以在执行我的 NSOperation 主函数期间,当我检查 isCancelled 属性时,它总是返回 NO。事实上,在 NSOperationQueue 上调用 cancelAllOperation 之后。 例如。

-(void)main
{
   if(self.isCancelled)
   {
    // Never executing this block :-(
   }

 }

有关更多详细信息,我正在我的 NSOperation 中进行一些网络调用。当我切换到其他视图时,会调用 cancelAllOperation。当网络响应在我的 NSOperation 中返回时,我正在检查 if(Self.isCancelled),现在我在另一个视图中(意味着 isCancelled 应该设置为 YES)。但这个检查总是失败。

【问题讨论】:

  • 您确定在您调用 cancelAllOperations 时您的操作尚未开始吗?您需要检查在整个操作执行过程中设置的 isCancelled 属性。
  • 我一直在我的操作主方法中检查 isCancelled 属性。我通过断点进行调试,发现调用 cancelAllOperation 方法后,当调用返回到此检查点 if(self.isCancelled) 时,它总是返回 NO。
  • 您是否在您的 NSOperation 上覆盖 cancel 方法?如果是这样,你可以发布它吗?如果没有,您可以覆盖(调用 super)并在那里放置一个日志或断点以查看它是否被调用?
  • 是的,我试图覆盖 NSOperation 子类中的 -(void)cancel 方法。它永远不会被调用。但是如果我在 viewDidLoad 中的 addOpperation 之后调用 cancelAllOperation,它就会被调用。
  • 在所有方法中记录对象的身份。确保您正在对您认为自己是的对象进行操作。例如,它 (self) 是同一个实例吗? self.operationQueue 两个地方都一样吗?

标签: ios objective-c multithreading nsoperation nsoperationqueue


【解决方案1】:

您的操作在加载viewDidLoad 中的视图后被添加到队列中,然后队列将承担开始操作的责任。

由于您在视图消失时取消了操作 (viewWillDisappear),因此操作很可能在此时完成。换句话说,您的操作在被终止后被取消。您可以检查isExecuting 属性以了解操作是否正在运行。

【讨论】:

  • 我一直在我的操作主方法中检查 isCancelled 属性。我通过断点进行调试,发现调用 cancelAllOperation 方法后,当调用返回此检查点时,如果(self.isCancelled)它总是返回 NO。仅当我的操作正在执行时,才会在此检查点调用。
【解决方案2】:

您的操作可能不再运行,因此不会被取消。 (一旦您的操作完成,操作队列将不再跟踪它,因此调用cancelAllOperations 不会做任何事情。)

如果您等待的网络响应是调用回调而不是阻止对main 的调用,则您的操作将已经完成(当 main 返回时)。您可以通过使用“并发”操作(请参阅 NSOperation 文档;您可以指示何时完成,而不是仅在 main 返回时自动完成)或使用同步网络调用(因此 main 直到你真的完成了)。

【讨论】:

  • 我明白你的意思。当我的响应到来时,我正在检查 isCancelled 属性,如果是,我将返回,否则我将使用来自响应的新内容重新加载我的 tabelView。现在我想做的是,如果我不在那个视图中,那么当响应返回时,它应该检查 isCancelled 属性,如果我当前不在那个视图中,则不应该重新加载我的 tabelView。那么你能给我一点提示,比如如何处理这种情况吗?
  • 好吧,您可以使用同步网络方法,就像我建议的那样,然后检查 isCancelled (因为您的操作仍将执行)。或者,您可以使用第三方库,如 AFNetworking,它具有可取消的 NSOperations 用于已经构建的网络活动。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-14
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多