等待异步任务完成完成块,然后返回应用程序委托 [英] Wait for async task to finish completion block before returning in app delegate
问题描述
我正在使用UIManagedDocument
的子类在项目中使用Core Data.关键是子类返回一个单例实例,以便我的屏幕可以简单地调用它,并且所有托管对象的上下文都保持不变.
I'm using a subclass of UIManagedDocument
to use Core Data in my project. The point is for the subclass to return a singleton instance so that my screens can simply call it and the managed object context remains the same for all of them.
在使用UIManagedDocument
之前,我需要通过打开它(如果其文件路径已存在)或通过创建它(如果尚不存在)来进行准备.我在子类中创建了一个便捷方法prepareWithCompletionHandler:
,以方便这两种情况.
Before using the UIManagedDocument
, I need to prepare it by opening it if its file path already exists, or creating it if it doesn't yet. I created a convenience method prepareWithCompletionHandler:
in the subclass to facilitate both scenarios.
@implementation SPRManagedDocument
// Singleton class method here. Then...
- (void)prepareWithCompletionHandler:(void (^)(BOOL))completionHandler
{
__block BOOL successful;
// _exists simply checks if the document exists at the given file path.
if (self.exists) {
[self openWithCompletionHandler:^(BOOL success) {
successful = success;
if (success) {
if (self.documentState != UIDocumentStateNormal) {
successful = NO;
}
}
completionHandler(successful);
}];
} else {
[self saveToURL:self.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
successful = success;
if (success) {
if (self.documentState != UIDocumentStateNormal) {
successful = NO;
}
}
completionHandler(successful);
}];
}
}
@end
我想做的是在我的应用程序委托的didFinishLaunchingWithOptions
中调用此准备方法,并在最后返回YES
或NO
之前等待完成块被执行.我目前的方法行不通.
What I'm trying to do is call this preparation method in my app delegate's didFinishLaunchingWithOptions
and wait for the completion block to be executed BEFORE returning either YES
or NO
at the end. My current approach doesn't work.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
__block BOOL successful;
SPRManagedDocument *document = [SPRManagedDocument sharedDocument];
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[document prepareWithCompletionHandler:^(BOOL success) {
successful = success;
}];
});
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
});
return successful;
}
在返回successful
之前,如何等待直到调用prepareWithCompletionHandler
中的完成处理程序?我真的很困惑.
How can I wait until the completion handler in prepareWithCompletionHandler
is called before returning successful
? I'm really confused.
推荐答案
我不确定为什么didFinishLaunching
返回状态取决于完成处理程序的成功,因为您显然甚至没有考虑launchOptions
.我不希望看到您在此处发出同步调用(或更准确地说,是使用信号量将异步方法转换为同步方法),因为它会使应用程序变慢,并且如果它的速度足够慢,您可能会被杀死看门狗过程.
I'm unsure why the didFinishLaunching
return status is dependent upon the success of your completion handler as you're not apparently even considering launchOptions
. I'd hate to see you put an synchronous call (or more accurately, use a semaphore to convert an asynchronous method into a synchronous one) here, as it will slow down the app and, if its slow enough, you risk being killed by the watch dog process.
信号量是使异步过程同步的一种常用技术:
Semaphores are one common technique for making an asynchronous process synchronous:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
__block BOOL successful;
SPRManagedDocument *document = [SPRManagedDocument sharedDocument];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[document prepareWithCompletionHandler:^(BOOL success) {
successful = success;
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return successful;
}
但是,在进一步回顾prepareWithCompletionHandler
的功能时,显然是在调用将自己的完成块分派到主队列的方法,因此任何试图使该同步完成的尝试都会死锁.
But, upon further review of what prepareWithCompletionHandler
is doing, it's apparently calling methods that dispatch their own completion blocks to the main queue, so any attempts to make this synchronous will deadlock.
因此,请使用异步模式.如果要在didFinishLaunchingWithOptions
中启动此操作,可以让它发布通知:
So, use asynchronous patterns. If you want to initiate this in the didFinishLaunchingWithOptions
, you can have it post a notification:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
__block BOOL successful;
SPRManagedDocument *document = [SPRManagedDocument sharedDocument];
[document prepareWithCompletionHandler:^(BOOL success) {
successful = success;
[[NSNotificationCenter defaultCenter] postNotificationName:kDocumentPrepared object:nil];
}];
return successful;
}
然后您可以让视图控制器addObserverForName
观察此通知.
And you can then have your view controller addObserverForName
to observe this notification.
或者,您可以将此代码从应用程序委托中移出,并移至该视图控制器中,从而无需通知.
Alternatively, you can move this code out of the app delegate and into that view controller, eliminating the need for the notification.
这篇关于等待异步任务完成完成块,然后返回应用程序委托的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!