首先,让我说我强烈阻止这样做。您的主线程正在等待,在等待呼叫完成时什么都不做。在某些情况下,如果系统没有在主线程上响应,系统会终止您的应用。这非常不寻常。
我想你应该是决定何时/如何使用各种编程工具的人。
这一个完全是你想要的...阻塞主线程,直到完成处理程序运行。同样,我不建议这样做,但是,嘿,这是一个工具,我会好好NRA立场:枪不杀人...
__block BOOL waitingOnCompletionHandler = YES;
[object doSomethingWithCompletionHandler:^{
// Do your work in the completion handler block and when done...
waitingOnCompletionHandler = NO;
}];
while (waitingOnCompletionHandler) {
usleep(USEC_PER_SEC/10);
}
另一种选择是执行run循环。但是,这并不是真正的同步,因为运行循环实际上会处理其他事件。我在一些单元测试中使用了这种技术。它与上面类似,但仍然允许其他内容在主线程上发生(例如,完成处理程序可能会调用主队列上的操作,这可能无法在前一个方法中执行)。
__block BOOL waitingOnCompletionHandler = YES;
[object doSomethingWithCompletionHandler:^{
// Do your work in the completion handler block and when done...
waitingOnCompletionHandler = NO;
}];
while (waitingOnCompletionHandler) {
NSDate *futureTime = [NSDate dateWithTimeIntervalSinceNow:0.1];
[[NSRunLoop currentRunLoop] runUntilDate:futureTime];
}
还有其他的方法为好,但这些都是很简单,易于理解,并伸出像突兀,所以很容易知道你是标新立异。
我还应该注意,我从来没有遇到过很好的理由在测试以外的任何事情上做到这一点。你可以死锁你的代码,而不是从主运行循环返回是一个滑坡(即使你自己手动执行它 - 请注意,称为你的东西仍在等待,再次运行该循环可能会重新输入该代码,或导致一些其他问题)。
异步API很棒。条件变量方法或对并发队列使用屏障是在使用其他线程时进行同步的合理方法。同步主线程与您应该做的事情相反。
祝你好运...并确保你注册你的枪,并始终携带你隐藏的武器许可证。这当然是狂野的西部。总是有一个约翰韦斯利哈登在那里寻找枪战。
...谢谢你的时间。我试图搜索没有块的旧API开放文档。任何想法,这是如何实现的? – 2012-05-08 11:02:22
UIManagedDocument是一个相对较新的接口,我不认为它有过同步API。在内部,它有两个ManagedObjectContext对象...一个在主线程中,一个使用私有调度队列。所有IO操作都发生在后台,所以类的性质决定了使用异步API。在块之前,异步API使用委托或通知让调用者知道操作何时完成。 – 2012-05-08 12:36:53
这不行,当我尝试下面的代码: __block BOOL waitingOnCompletionHandler = YES;如果(成功)DLog(@“open document succeed!”);如果(成功){0} self.managedObjectContext = _managedDocument.managedObjectContext; waitingOnCompletionHandler = NO; } }];同时(waitingOnCompletionHandler)使用USLE_PER_SEC/10; } 主线程永远卡在那里... – zolibra 2013-06-27 01:22:41