我不确定如何处理块。例如,在我的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
}
}
答案 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将变量从块外部带入作用域,并在剩余的周围代码完成时运行块。
在这种情况下,您正在使用完成块。你可以在那里调用方法,只要在完成所有代码完成后调用它们的适当时间。