在iOS中,dispatch队列可以实现类似java的Notify/Wait机制来保证线程同步。
1.创建信号量,参数是0,用来指示需不需要等待
dispatch_semaphore_t sema=dispatch_semaphore_create(0);
2.等待信号量,信号量如果大于等于0,则表示等待,这里设置超时时间DISPATCH_TIME_FOREVER表示永久等待
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
3.使用信号量
dispatch_semaphore_t sema=dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗时的操作
dispatch_semaphore_signal(sema); //让sema变量减1
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
注:上面就完成了简单的同步,当然,你还可以设计出更复杂的程序,比如《消费者与生产者的关系》
举一个常用的例子,获取联系人权限
+(NSString *)getContacts{
//获取通讯录权限
ABAuthorizationStatus authStatus = ABAddressBookGetAuthorizationStatus();
if(authStatus!=kABAuthorizationStatusAuthorized)
{
//是否有通讯录权限
__block BOOL accessGranted = NO;
ABAddressBookRef tmpAddressBook = ABAddressBookCreateWithOptions(NULL, NULL);
dispatch_semaphore_t sema=dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(tmpAddressBook, ^(bool greanted, CFErrorRef error){
accessGranted = greanted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
if(accessGranted == NO){
return @"[]";
}
}
//读取联系人----------此处省略联系人读取步骤-------------------
}
注意:dispatch_semaphore_signal(sema)该函数必须在设置被设置变量的后面
accessGranted = greanted;
dispatch_semaphore_signal(sema);
如果顺序出现问题,那么aceesGranted的值将永远是NO,因为dispatch_semaphore_signal改变sema后会立即让dispatch_semaphore_wait是否继续等待,如果不需要,则后续代码立即执行,从而造成执行下面的语句,返回 “[]”
if(accessGranted == NO){
return @"[]";
}