在NSOperation中使用块的方法 - 它是如何工作的?

时间:2012-03-30 22:40:39

标签: objective-c ios objective-c-blocks nsoperation nsoperationqueue

我正在开发一个必须在iOS4上工作的iOS项目。我有一个NSOperationQueue,我添加了一个操作。操作的主要方法如下所示:

-(void)main 
{
    [self.client getStuffSuccess:^(Stuff *s) {
        //Do something on success
    } failure:^(NSError *error) {
        //Do something on failure
    }
}

只有在getStuff调用成功或失败时才会调用块内的代码。我认为同时,我的操作将从NSOperationQueue中删除,并且不会调用该块。但是,我测试了它,并且实际上调用了块。无论客户端是在调用dispatch_get_main_queue还是在调用它的线程上调用成功块,都会调用它 - 在这种情况下是上面的操作。

在调用块之前,方法isFinished实际上返回true(我覆盖了isFinished方法并检查了值),所以有人可以解释一下这个块是如何被调用的?

我问这一切是因为虽然这对于一次调用工作正常,但是当我在几百次迭代的循环中添加它时,我得到一个EXC_BAD_ACCESS并且理解上面的内容可能会帮助我进行调试。

3 个答案:

答案 0 :(得分:1)

  

只有在getStuff调用成功或失败时才会调用块内的代码。我认为同时,我的操作将从NSOperationQueue中删除,并且不会调用该块。

是什么让你相信这一点。块是一个闭包,一个独立的代码块。它不依赖于某些其他对象(在本例中为NSOperation)的存在以便存在。您可能希望依赖于其他对象,但这取决于您执行。理想情况下,我会使getStufSuccess:失败:同步。如果你不能,你可以使用NSCondition或调用NSRunLoop方法来廉价地阻止线程,直到它完成。

您还需要在此处考虑线程安全性。你的问题可能与操作消失无关,但是你的块做了一些非线程安全的事情。

答案 1 :(得分:0)

如果您的-getStuffSuccess:failure没有阻止该线程(即该方法是异步的),那么您的-main将完成,您的operationQueue可能会在调用成功或失败块之前解除您的操作。您可以通过添加:

来阻止该线程
while(notProcessed){
    sleep(0.1);
    //Make sure your success and failure functions update notProcessed BOOL
}

这样main永远不会在您有机会调用闭包之前完成。或者只使用同步方法。这通常很好,因为无论如何你都不会在UI线程上。

答案 2 :(得分:0)

由于getStuffSuccess:失败是异步的,因此您需要使用并发操作。这是一篇有用的博文: http://www.dribin.org/dave/blog/archives/2009/05/05/concurrent_operations/