iOS 9使用Contacts框架获取联系人,如果为了适配低于IOS 9版本还是用AddressBook吧,或者通过判断系统版本号来适配不同的手机。Apple官方文档
新框架中将要使用最多的应该就是CNContactStore这个类了,官方对其的定义是一个线程安全的,用来执行查询和修改操作的类。此外官方还针对于这个类的使用给出了几点小建议。
1.只去查询那些你需要的联系人属性。
2.当查询所有联系人并缓存结果时,首先查询所有联系人的identifier,然后通过identifier来查询所需要的详细的联系人信息。
3.想取出多个联系人信息时,可以先收集联系人的唯一identifier,然后通过identifier来查询所需要的详细的联系人信息。
4.如果缓存了联系人信息,那么当接收到CNContactStoreDidChangeNotification时你需要刷新数据。
5.CNContactStore的查询方法中执行了I/O操作,所以应该避免在主线程中执行。
首先导入Contacts.frame和ContactsUI.frame
然后在info.plist中添加NSContactsUsageDescription 后面的字符串是你向用户申请权限的描述。
请求权限
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
switch (status) {
case CNAuthorizationStatusNotDetermined:
NSLog(@"用户还没有决定是否可以访问");
[self requestDetermain];
break;
case CNAuthorizationStatusDenied:
NSLog(@"不可以访问联系人数据库");
break;
case CNAuthorizationStatusAuthorized:
NSLog(@"可以访问联系人数据库");
break;
case CNAuthorizationStatusRestricted:
NSLog(@"这个状态说明应用不仅不能够访问联系人数据,并且用户也不能在设置中改变这个状态");
break;
default:
break;
}
});
iOS8之后是可以直接从应用内跳转到设置页面来修改通讯录权限的
//跳转到设置应用访问联系人界面
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
当联系人发生变化的时候通知,比如我们项目保存的联系人数据的刷新
//联系人发生变化通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(addressBookDidChange:) name:CNContactStoreDidChangeNotification object:nil];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)addressBookDidChange:(NSNotification*)aNotification{
NSLog(@"%@",aNotification);
}
请求授权读取联系人提示框,当然这个也可以自己定义
//请求授权提示框
-(void)requestDetermain{
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
//获取联系人
[self obtainContact:store];
}
}];
}
已经拿到用户的授权了,那么接下来就可以读取用户数据了。首先,我们需要创建一个CNContactFetchRequest对象。这里简单说一下predicate和keysToFetch这两个参数,其中的predicate谓词参数,必须是由CNContact+Predicates生成的。至于keysToFetch参数,个人理解是由两部分组成的,其中一部分可以去CNContact.h的最下面查,另一部分可以查询CNContactFormatter.h
获取联系人列表
-(void)obtainContact:(CNContactStore *)store{
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[[CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName],CNContactPhoneNumbersKey]];
NSError *error = nil;
self.array = [NSMutableArray array];
[store enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
[self.array addObject:contact];
}];
}
如果没什么意外情况的话,所需要的通讯录信息都已经存在这个数组里面了,需要注意的是这个方法的结果不是一次性返回的,这个可以通过监控stop参数来确定。