关于iOS块的困惑

时间:2012-06-19 03:17:21

标签: ios objective-c-blocks

我不确定如何处理块。例如,在我的viewDidLoad中,我调用了一个函数“useDocument”来设置Core Data。我希望只要Core Data准备好使用,就会调用另一个函数来处理一些查询。就像ASIHTTPRequest一样,当客户端收到响应时,会调用一个函数来处理响应。

我认为触发函数不是使用块的正确方法。但是正确的方法是什么?

- (void)useDocument
{
    if (!self.database) {
        self.database = [DataModelDocument sharedDocument];
    }

    if (![[NSFileManager defaultManager] fileExistsAtPath:[self.database.fileURL path]]) {
        // does not exist on disk, so create it
        [self.database saveToURL:self.database.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
                if (!success) {
                    NSLog(@"database doesn't exist on disk, we fail to create it");
                }
        }];
    } else if (self.database.documentState == UIDocumentStateClosed) {
        // exists on disk, but we need to open it
        [self.database openWithCompletionHandler:^(BOOL success) {
            if (!success) {
                NSLog(@"database exists on disk, but we fail to open it");
            }
        }];
    } else if (self.database.documentState == UIDocumentStateNormal) {
        // already open and ready to use
    }
}

2 个答案:

答案 0 :(得分:1)

没有正确的方法来使用块,因为没有正确的方法来使用函数。

块是功能。多一个功能,但不是很多不同。所以,让我们暂时忘记这些差异。功能

使用函数,你会写类似

的东西
void callback (BOOL success) {
    if (success) {
        // do something useful
    }
}

[database openWithCallback: &callback];

这里有点小的结局。杂交。

Blocks允许您在线编写回调。

[self.database openWithCompletionHandler: ^(BOOL success) {
    if (!success) {
        // oops, handle that
    }
}];

在这种特殊情况下,块无法解决任何问题。它们的成本更高。

当你使用很多它们时,好处就会显现出来。如果您将操作编写为完全异步,则可以以简化的方式编写代码。

伪码:

dispatch block: ^(){
    some heavy computation here
    dispatch block: ^(){
        computation done, update the UI or something
    }
}

非常简单的例子。当然,完全可以用函数编写它。但不是那么可读。

现在假设您正在调度大量的块,您可以创建块组,然后在组完全执行时执行块。非常容易编写,非常容易阅读。这开始是处理各地函数指针的噩梦。

现在,什么使得一个块不仅仅是一个函数?

块是一个功能。有了背景。块可以访问同一范围内的变量。在上面的简单例子中,工作块可以访问调用范围,完成块可以访问调用范围和工作块范围。当然,这可以通过功能和结构来完成。使用大量代码,更难阅读。块更优雅地解决了这个问题。

我建议你阅读Grand Central Dispatch。这显然是街区显示其真正潜力和表现力的地方。

答案 1 :(得分:0)

您可以将块视为一种“有状态线程”。我强调“有点”。它是代码和变量封装成一个漂亮整洁的小“代码块”。

您可以使用__block将变量从块外部带入作用域,并在剩余的周围代码完成时运行块。

在这种情况下,您正在使用完成块。你可以在那里调用方法,只要在完成所有代码完成后调用它们的适当时间。