1、ABAddressBook
1、在ios6之前,访问系统通讯录是不需要征得用户同意的,访问通讯录的方法如下所示:
在ios6(包括)ios6之后,访问系统通讯录是需要征的用户同意的,访问通讯录的方法也改变了,方法如下所示:
ABAddressBookRef ABAddressBookCreateWithOptions ( CFDictionaryRef options, CFErrorRef *error);
具体的视线可以参考我写的代码:
代码补充说明:
[按照网上所属,block里面的方法是只有在用户成功授权的情况下,才会走,不过我写了demo去测试,发现,无论用户同不同意授权,block都会调用,信号量都会加1,程序会继续向下进行]。
如果用户同意,则
CFArrayRef results = ABAddressBookCopyArrayOfAllPeople(addressBook)方法返回的结果就是系统通讯录的copy;
如果用户不同意,
CFArrayRef
results =
ABAddressBookCopyArrayOfAllPeople
(addressBook)返回的结果是空的。
为了安全判断,如下代码所示,我在copy通讯录信心前又加了安全判断,判断用户是否成功授权。
dispatch_semaphore_t
sema =
dispatch_semaphore_create
(
0
);
if ([ UIDevice currentDevice ]. systemVersion . floatValue >= 6.0 ) {
addressBook = ABAddressBookCreateWithOptions ( NULL , NULL );
// 发出访问通讯录的请求
ABAddressBookRequestAccessWithCompletion (addressBook, ^( bool granted, CFErrorRef error){
// 信号量加 1
dispatch_semaphore_signal (sema);
});
// 如果信号量仍未 0 ,则等待,知道得到用户的授权
dispatch_semaphore_wait (sema, DISPATCH_TIME_FOREVER );
} else {
//ios6 之前的方法
addressBook = ABAddressBookCreate ();
}
#warnging
if ( ABAddressBookGetAuthorizationStatus () == kABAuthorizationStatusAuthorized ) {
CFArrayRef results = ABAddressBookCopyArrayOfAllPeople (addressBook);
long peopleCount = CFArrayGetCount (results);
if (peopleCount >= 0 ) {
[ self presentABPeopleNav ];
}
}
}
if ([ UIDevice currentDevice ]. systemVersion . floatValue >= 6.0 ) {
addressBook = ABAddressBookCreateWithOptions ( NULL , NULL );
// 发出访问通讯录的请求
ABAddressBookRequestAccessWithCompletion (addressBook, ^( bool granted, CFErrorRef error){
// 信号量加 1
dispatch_semaphore_signal (sema);
});
// 如果信号量仍未 0 ,则等待,知道得到用户的授权
dispatch_semaphore_wait (sema, DISPATCH_TIME_FOREVER );
} else {
//ios6 之前的方法
addressBook = ABAddressBookCreate ();
}
#warnging
if ( ABAddressBookGetAuthorizationStatus () == kABAuthorizationStatusAuthorized ) {
CFArrayRef results = ABAddressBookCopyArrayOfAllPeople (addressBook);
long peopleCount = CFArrayGetCount (results);
if (peopleCount >= 0 ) {
[ self presentABPeopleNav ];
}
}
}
2、ABPeoplePickerNavigationController
ABPeoplePickerNavigationController的使用就和UIImagePickerViewController的使用是一样的。
在ios8之前需要
需要用户授权,授权成功之后才可以访问
但是在ios8之后,不会提示用户是否授权,可以直接访问
苹果官方文档解释如下所示:
In iOS 8 and later bringing up a people-picker navigtion controller does not require the app to have access to a user’s contacts, and the user will not be prompted to grant access. If the app does not itself have access to the user’s contacts, a temporary copy of the contact selected by the user will be returned to the app.
ABPeoplePickerNavigationController
也有对应的代理方法,可以实现用户对通讯录的操作。要注意的时,ios7和ios8使用的代理方法是有区别的。ios8下会有意想不到的bug,到目前为止遇到了两个:
第一个bug:进入到信息人详情页后,会突然dismiss
解决办法是:
在实例化
ABPeoplePickerNavigationController时,加上下面的代码
if
([
UIDevice
currentDevice
].
systemVersion
.
floatValue
>=
8.0
){
// 点击联系人跳转到联系人详情界面
peoplePicker. predicateForSelectionOfPerson = [ NSPredicate predicateWithValue : FALSE ]; // 防止进入详情页的时候突然 dismiss , ios8 的 bug
}
// 点击联系人跳转到联系人详情界面
peoplePicker. predicateForSelectionOfPerson = [ NSPredicate predicateWithValue : FALSE ]; // 防止进入详情页的时候突然 dismiss , ios8 的 bug
}
第二个bug:点击联系电话时,跳转到了拨打电话的界面
bug原因是:ios7和ios8下要实现的代理方法是不同的
解决办法是:stackoverflow网站的建议如下:
意思就是如果是ios8,就是在ios的代理方法中调用ios7下的代理方法
Keep the old delegate method in place to support iOS 7 or earlier. What I do in my app is call the iOS 7 delegate method from the iOS 8 delegate method:
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
[self peoplePickerNavigationController:peoplePicker shouldContinueAfterSelectingPerson:person property:property identifier:identifier];
}