目录
前言
iOS中通讯录的用法。
1.什么是CNContactStore
CNContactStore类是iOS中的一个框架,用于访问和管理设备上的通讯录数据。它提供了一种统一的方式来获取、添加、更新和删除联系人和群组,以及监听通讯录数据的变化。在iOS开发中,CNContactStore类具有重要性,因为它允许应用程序与设备上的通讯录进行交互,从而实现诸如获取联系人信息、同步联系人数据、发送通讯录相关的通知等功能。通过CNContactStore类,开发人员可以轻松地构建与通讯录相关的功能,提高应用程序的用户体验和功能性。
2.获取通讯录权限
因为手机通讯录信息数据敏感信息,因此我们需要请求用户的授权。在用户未授权我们的app访问通讯录权限之前,app无法请求通讯录信息。描述要简单、清晰,让用户有信心授权app访问。
请求用户授权访问手机通讯录之前,我们按照下面的步骤配置app项目。
1.配置plist文件
首先我们需要再项目的plist文件中添加NSContactsUsageDescription属性,这个key对应的值用来描述app要执行的操作以及我们为什么要请求用户授权访问通讯录。如果没有配置这个key,app请求通讯录的时候,程序会终止。
2.请求访问通讯录授权
我们先看下通讯录权限状态的类型定义,通讯类权限状态是一个CNAuthorizationStatus类型的枚举,定义如下:
typedef NS_ENUM(NSInteger, CNAuthorizationStatus){
CNAuthorizationStatusNotDetermined = 0,//用户未决定是否授权访问
CNAuthorizationStatusRestricted,//授权受限制
CNAuthorizationStatusDenied,//拒绝授权
CNAuthorizationStatusAuthorized//已经授权
} NS_ENUM_AVAILABLE(10_11, 9_0);
这里需要注意的是只有当通讯录授权状态为CNAuthorizationStatusNotDetermined的时候,系统才会向用户展示一个弹窗,让用户选择是否授权app访问通讯录权限。其它状态下,系统不会再展示让用户选择是否授权状态的弹窗。
app调用requestAccessForEntityType:completionHandler类方法,返回当前通讯录的授权状态。demo如下:
objectivec
- (void)requestContactAccess{
// 检查授权状态
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
// 请求授权
// 请求授权
if (status == CNAuthorizationStatusNotDetermined) {
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
// 用户授予了授权,可以继续访问通讯录数据
NSLog(@"用户已授权访问通讯录");
} else {
// 用户拒绝了授权,需要适当地处理这种情况
NSLog(@"用户拒绝了访问通讯录的授权请求");
}
}];
} else if (status == CNAuthorizationStatusDenied || status == CNAuthorizationStatusRestricted) {
// 用户已经拒绝了授权或者授权受限,需要适当地处理这种情况
NSLog(@"用户拒绝了访问通讯录的授权请求");
} else {
// 用户已经授予了授权,可以继续访问通讯录数据
NSLog(@"用户已授权访问通讯录");
}
}
3.通讯录访问权限的其它配置
如果我们需要再iOS13以及之后的版本读写联系人字段的时候,需要添加权限到app,得到apple的许可才能时候,在未得到Apple许可之前,是无法分发app的。具体的配置看这里。
文档很详细,因为暂时没有发布app的需求,这个就不详细描述了。
3.获取通讯录中的联系人
获取通讯录我们可以使用CNContactStore类,CNContactStore类是iOS中用于访问和操作通讯录数据的主要接口之一。它提供了一组方法来执行各种通讯录操作,包括读取、写入、更新和删除联系人、群组等。
获取通讯录中的联系人信息的时候,我们需要使用CNContactFetchRequest创建通讯录请求。使用步骤如下:
1.实例化CNContactStore对象,
CNContactStore *store = [[CNContactStore alloc] init];
2.实例化CNContactFetchRequest对象
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]];
3.发起通讯录信息请求,完整代码如下:
objectivec
- (void)fetchAllContactsInfor {
CNContactStore *store = [[CNContactStore alloc] init];
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey, CNContactPostalAddressesKey]];
[store enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
//后续操作
}];
}
这里需要注意的是通讯录请求是个异步耗时操作,建议使用异步多线程去处理。
4.获取通讯录中的群组
我们使用 CNContactStore 类的 groupsMatchingPredicate:error: 方法来获取通讯录中的所有群组。该方法返回符合指定条件的通讯录群组数组。下面是一个获取通讯录群组的示例代码:
objectivec
- (void)fetchAllGroupsCompletion:(void (^)(NSArray<CNGroup *> * _Nullable groups, NSError * _Nullable error))completion {
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!granted) {
NSError *accessError = [NSError errorWithDomain:@"com.yourdomain.ContactManager" code:1 userInfo:@{NSLocalizedDescriptionKey: @"Access to contacts not granted"}];
if (completion) {
completion(nil, accessError);
}
return;
}
NSError *fetchError = nil;
NSArray<CNGroup *> *groups = [store groupsMatchingPredicate:nil error:&fetchError];
if (fetchError) {
if (completion) {
completion(nil, fetchError);
}
} else {
if (completion) {
completion(groups, nil);
}
}
}];
}
5.操作联系人
1.增加联系人
要在iOS中增加一个联系人信息,可以使用 CNMutableContact 类来创建一个可变的联系人对象,然后通过 CNContactStore 类的 executeSaveRequest:error: 方法将其保存到通讯录中。以下是一个示例代码:
objectivec
- (void)addContactWithName:(NSString *)name phoneNumber:(NSString *)phoneNumber {
// 创建一个可变的联系人对象
CNMutableContact *contact = [[CNMutableContact alloc] init];
// 设置联系人的姓名
contact.givenName = name;
// 创建一个电话号码对象,并添加到联系人的电话号码数组中
CNLabeledValue *phoneNumberValue = [CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberMobile value:[CNPhoneNumber phoneNumberWithStringValue:phoneNumber]];
contact.phoneNumbers = @[phoneNumberValue];
// 创建联系人存储请求
CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
[saveRequest addContact:contact toContainerWithIdentifier:nil]; // 使用默认的通讯录容器
// 获取联系人存储对象
CNContactStore *store = [[CNContactStore alloc] init];
// 将联系人存储请求提交给通讯录
NSError *error = nil;
if (![store executeSaveRequest:saveRequest error:&error]) {
NSLog(@"Error adding contact: %@", error.localizedDescription);
} else {
NSLog(@"Contact added successfully!");
}
}
2.更新联系人信息
要在iOS中更新联系人信息,可以使用 CNMutableContact 类创建一个可变的联系人对象,并将其修改后保存到通讯录中。以下是一个示例代码:
objectivec
- (void)updateContactWithIdentifier:(NSString *)identifier withName:(NSString *)name phoneNumber:(NSString *)phoneNumber {
// 获取联系人对象
CNContactStore *store = [[CNContactStore alloc] init];
NSError *error = nil;
CNContact *contact = [store unifiedContactWithIdentifier:identifier keysToFetch:@[CNContactGivenNameKey, CNContactPhoneNumbersKey] error:&error];
if (error) {
NSLog(@"Error fetching contact: %@", error.localizedDescription);
return;
}
// 创建一个可变的联系人对象,并复制原始联系人的属性
CNMutableContact *mutableContact = [contact mutableCopy];
// 更新联系人的姓名和电话号码
mutableContact.givenName = name;
CNPhoneNumber *newPhoneNumber = [CNPhoneNumber phoneNumberWithStringValue:phoneNumber];
CNLabeledValue *phoneNumberValue = [CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberMobile value:newPhoneNumber];
mutableContact.phoneNumbers = @[phoneNumberValue];
// 创建联系人存储请求
CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
[saveRequest updateContact:mutableContact];
// 提交联系人存储请求给通讯录
if (![store executeSaveRequest:saveRequest error:&error]) {
NSLog(@"Error updating contact: %@", error.localizedDescription);
} else {
NSLog(@"Contact updated successfully!");
}
}
在这个示例中,我们首先通过联系人的唯一标识符获取到原始的 CNContact 对象。然后,我们创建一个可变的 CNMutableContact 对象,并使用原始联系人的属性对其进行初始化。接下来,我们更新了联系人的姓名和电话号码。最后,我们创建了一个 CNSaveRequest 对象,并通过 updateContact: 方法将修改后的联系人对象添加到保存请求中。最终,我们使用 CNContactStore 对象的 executeSaveRequest:error: 方法来执行保存请求。
3.删除联系人信息
要在iOS中删除联系人信息,可以使用 CNMutableContact 类创建一个可变的联系人对象,并将其标记为已删除,然后保存到通讯录中。以下是一个示例代码:
objectivec
- (void)deleteContactWithIdentifier:(NSString *)identifier {
// 获取联系人对象
CNContactStore *store = [[CNContactStore alloc] init];
NSError *error = nil;
CNContact *contact = [store unifiedContactWithIdentifier:identifier keysToFetch:@[] error:&error];
if (error) {
NSLog(@"Error fetching contact: %@", error.localizedDescription);
return;
}
// 创建一个可变的联系人对象,并将其标记为已删除
CNMutableContact *mutableContact = [contact mutableCopy];
mutableContact.contactType = CNContactTypePerson;
// 创建联系人存储请求
CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
[saveRequest deleteContact:mutableContact];
// 提交联系人存储请求给通讯录
if (![store executeSaveRequest:saveRequest error:&error]) {
NSLog(@"Error deleting contact: %@", error.localizedDescription);
} else {
NSLog(@"Contact deleted successfully!");
}
}
在这个示例中,我们首先通过联系人的唯一标识符获取到原始的 CNContact 对象。然后,我们创建一个可变的 CNMutableContact 对象,并使用原始联系人的属性对其进行初始化。接下来,我们将可变联系人对象的 contactType 属性设置为 CNContactTypePerson,这将将联系人标记为普通个人联系人。最后,我们创建了一个 CNSaveRequest 对象,并通过 deleteContact: 方法将标记为已删除的联系人对象添加到保存请求中。最终,我们使用 CNContactStore 对象的 executeSaveRequest:error: 方法来执行保存请求。
6.监听通讯录变化
要在iOS应用中监听通讯录的变化,可以使用 CNContactStoreDidChangeNotification 通知。
8.参考文章
2.权限配置