我想启动一个在另一个线程上运行的任务“以防万一”,以尽量减少用户稍后必须等待的时间。如果有时间完成,则用户不必等待,但如果尚未完成,则需要等待。
例如,viewDidLoad:
当用户按下屏幕上的按钮时,将需要在其中打开一个数据库。如果我等到用户实际按下按钮才打开数据库,则会出现延迟。所以我想早点打开它。由于我不知道打开需要多长时间,也不知道用户点击按钮需要多长时间,所以我需要一种说法,如果其他任务尚未完成,则等待,否则继续.
例如:
@implementation aViewController
- (void) viewDidLoad {
[self.dbManager openOrCreateDbWithCompletionHandler: ^(NSError *err) {
if( err ) NSLog( @"There was a problem opening the database" );
}];
}
- (IBAction) goButtonTouched: (id) sender {
// Wait here until the database is open and ready to use.
if( ???DatabaseNotAvailableYet??? ) {
[self putSpinnerOnScreen];
???BlockProgressHereUntilDatabaseAvailable???
[self takeSpinnerOffScreen];
}
// Use the database...
NSManagedObjectContext *context = [self theDatabaseContext];
// Build the search request for the attribute desired
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName: NSStringFromClass([Destinations class])];
request.predicate = [NSPredicate predicateWithFormat: @"dId == %@", sender.tag];
request.sortDescriptors = nil;
// Perform the search
NSError *error = nil;
NSArray *matches = [context executeFetchRequest: request error: &error];
// Use the search results
if( !matches || matches.count < 1 ) {
NSLog( @"Uh oh, got a nil back from my Destination fetch request!" );
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"No Info"
message: @"The database did not have information for this selection"
delegate: nil
cancelButtonTitle: @"OK"
otherButtonTitles: nil];
[alert show];
} else {
MyOtherViewController *movc = [[MyOtherViewContoller alloc] init];
movc.destDetails = [matches lastObject];
[self.navigationController pushViewController: movc animated: YES];
}
}
@end
我希望屏幕上永远不会出现微调器,也不会给用户带来任何延迟,但是,由于我不知道建立数据库连接需要多长时间,所以我必须为它没有准备好做好准备当用户按下按钮时。
我不能在完成时使用回调,openOrCreateDbWithCompletionHandler:
因为那时我不想做任何事情,只有当用户按下按钮时。
我考虑过使用信号量,但似乎我只会发出一次信号(在openOrCreateDbWithCompletionHandler:
调用的完成处理程序中),但每次按下按钮时都会等待它。这似乎只适用于第一次按下按钮。
我考虑过使用dispatch_group_async()
for openOrCreateDbWithCompletionHandler:
then dispatch_group_wait()
ingoButtonTouched:
但由于openOrCreateDbWithCompletionHandler:
它在另一个线程上工作并立即返回,我认为不会设置等待状态。
我可以简单地设置一个我自己的标志,比如在 , 之前openOrCreateDbWithCompletionHandler:
,self.notOpenYet = YES;
然后在它的完成处理程序中做self.notOpenYet = NO;
,然后在goButtonTouched:
替换???DatabaseNotAvailableYet??? ,self.notOpenYet
但是我如何阻止其状态的进展?放入循环和计时器似乎很笨拙,因为我不知道等待是纳秒还是秒。
这似乎是一个很常见的情况,我相信你们都经常做这种事情,而且我的教育很差,但是我搜索了 stackOverflow 和网络,并没有找到一个令人满意的答案。