刚刚查了一下,iOS 9系统的市场份额大概占到了80%左右,所以如果你能够说服老板放弃剩下的20%左右的用户的话(我感觉老板不会被你忽悠),你现在就可以只使用Contacts这个新框架了,否则的话就还是乖乖的用AddressBook吧,或者通过判断系统版本号来适配不同的手机。
好吧,现在开始进入正题,这个新框架中将要使用最多的应该就是CNContactStore这个类了,官方对其的定义是一个线程安全的,用来执行查询和修改操作的类。此外官方还针对于这个类的使用给出了几点小建议。
1.只去查询那些你需要的联系人属性。
2.当查询所有联系人并缓存结果时,首先查询所有联系人的identifier,然后通过identifier来查询所需要的详细的联系人信息。
3.想取出多个联系人信息时,可以先收集联系人的唯一identifier,然后通过identifier来查询所需要的详细的联系人信息。
4.如果缓存了联系人信息,那么当接收到CNContactStoreDidChangeNotification时你需要刷新数据。
5.CNContactStore的查询方法中执行了I/O操作,所以应该避免在主线程中执行。
在项目中,首先我们可以调用授权状态的查询方法来确定应用的授权状态。
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
NotDetermined:这个状态说明用户暂未决定是否允许访问联系人数据库。当应用第一次安装在设备上时将处于此状态。
Restricted:这个状态说明应用不仅不能够访问联系人数据,并且用户也不能在设置中改变这个状态。这个状态是某些被激活的限制所导致的(比如说家长控制)。
Denied:这个状态说明用户不允许应用访问联系人数据。这个状态只能够被用户改变。
Authorized:这个状态是所有应用都希望拥有的,这表明应用能够自由访问联系人数据库,然后根据联系人数据来处理某些任务。
授权状态一共是上面的四种,我们需要分别对不同的授权状态来做出相应的操作。首先如果是Authorized的话,那么一切好说,接下来直接进行相应的通讯录操作就好了,而如果是NotDetermined的话,就调用一下请求授权的方法(下面会详细说明),至于剩下的两个方法,则只能弹窗提示用户去设置里面修改权限了。
那么接下来,我们假设调用上面的方法,得到的结果是NotDetermined,我们就需要调用下面的方法来请求授权,如果用户不同意,那就弹窗问他,不给我通讯录授权我怎么服务你啊(在这点上脉脉做的比较狠😄)。
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
}];
如果顺利的话,到这里我们就已经拿到用户的授权了,那么接下来就可以读取用户数据了。首先,我们需要创建一个
CNContactFetchRequest对象。这里简单说一下
predicate和keysToFetch这两个参数,其中的predicate谓词参数,必须是由CNContact+Predicates生成的。至于keysToFetch参数,个人理解是由两部分组成的,其中一部分可以去CNContact.h的最下面查,另一部分可以查询CNContactFormatter.h。下面是我写的一小段示例代码:
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参数来确定。(此外就是在这里我有一个疑问,希望理解的同学帮我解释一下。我在官方文档中看到一种说法就是其实只要调用查询方法,系统就会自动去请求授权。所以我对上面提到的那个请求授权的方法的调用时机不是完全的理解)。
那么最后,当我们获取到通讯录信息之后,可能会将数据暂存下来,这样就涉及到了一个数据刷新的问题,这个问题可以通过添加
CNContactStoreDidChangeNotification监听来解决,需要注意的是这个监听的响应次数是和通讯录中修改信息的条数相匹配的,所以一定要做好相应的处理。
到这里简单的获取通讯录信息功能应该实现了,最后说一下iOS8之后是可以直接从应用内跳转到设置页面来修改通讯录权限的,所以还是做一下系统适配的好,不然也许用户嫌麻烦就不去自己改了。
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
最后是作者唠叨时间,感谢大家对我的支持,尤其是上一篇文章大家对我的肯定,还是老样子,如果大家感觉对你有一定的帮助,就关注加喜欢吧,就当是小小满足一下我的虚荣心,我们一起进步。