美文网首页
系统通讯录的使用之基于 Contacts.framework 和

系统通讯录的使用之基于 Contacts.framework 和

作者: 不做待宰的猴子 | 来源:发表于2017-10-30 16:00 被阅读0次

    与ABPeoplePickerNavigationController相似,通过 CNContactPickerViewController 直接调取系统通讯录,只需要通过代理方法处理相应的需求即可。
    CNContactPickerDelegate代理方法:

    //点击调起页面的“取消”按钮时调用
    - (void)contactPickerDidCancel:(CNContactPickerViewController *)picker;
    //单选 列表页选中联系人返回
    - (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact;
    //单选 联系人详情页选中具体属性返回
    - (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty;
    //多选 列表页选中多个联系人后返回多个联系人
    - (void)contactPicker:(CNContactPickerViewController *)picker didSelectContacts:(NSArray<CNContact*> *)contacts;
    //多选 列表页选中多个联系人后返回多个属性
    //需要执行 返回被选中多个联系人的property 前提需设置:_contactPicker.predicateForSelectionOfProperty = [NSPredicate predicateWithValue:true];
    - (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperties:(NSArray<CNContactProperty*> *)contactProperties;
    

    获取用户通讯录中所有联系人信息:

    CNContactStore *contactStore = [[CNContactStore alloc] init];
    NSError *error;
    NSArray *keys = @[CNContactPhoneNumbersKey,CNContactFamilyNameKey,CNContactGivenNameKey];
    NSArray *allContacts = [contactStore unifiedContactsMatchingPredicate:NULL keysToFetch:keys error:&error];
    

    联系人信息解析过程与AddressBook.framework截然不同:

    for (CNContact *contact in allContacts) {
        NSString *familyNameString = contact.familyName;
        NSString *givenNameString  = contact.givenName;
        NSArray *mobileArray       = contact.phoneNumbers;
        
        for (int i = 0; i < mobileArray.count; i++) {
            CNLabeledValue *phoneValue = mobileArray[i];
            CNPhoneNumber *phoneNumber = phoneValue.value;
            NSString *phoneString      = phoneNumber.stringValue;
            phoneString = [self filterSymbolFromString:phoneString];
            if ([phoneString hasPrefix:numString]) {
                self.infoLabel.text = [NSString stringWithFormat:@"%@ (%@%@)", phoneString, familyNameString, givenNameString];
                return;
                
            }else {
                self.infoLabel.text = @"";
            }
        }
    }
    

    访问权限:

    CNContactStore *contactStore = [[CNContactStore alloc] init];
    if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] != CNAuthorizationStatusAuthorized) {
        [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (!granted) {
                UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"尚未获取访问权限" message:@"您未允许PeoploLink访问您的通讯录,请到设置中开启访问通讯录的权限" preferredStyle:UIAlertControllerStyleAlert];
                UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleDefault
    handler:^(UIAlertAction * _Nonnull action) {
                    
                }];
                [alertC addAction:sureAction];
                [self presentViewController:alertC animated:YES completion:nil];
                
            }else {
                NSError *error;
                NSArray *keys = @[CNContactPhoneNumbersKey,CNContactFamilyNameKey,CNContactGivenNameKey];
                allContacts   = [contactStore unifiedContactsMatchingPredicate:[NSPredicate predicateWithFormat:@""] keysToFetch:keys
    error:&error];
            }
        }];
        
    }else {
        NSError *error;
        NSArray *keys = @[CNContactPhoneNumbersKey,CNContactFamilyNameKey,CNContactGivenNameKey];
        allContacts   = [contactStore unifiedContactsMatchingPredicate:[NSPredicate predicateWithFormat:@""] keysToFetch:keys
    error:&error];
    }
    

    添加联系人

    - (void)addContact {
        NSString *name  = @"沙僧";
        NSString *phone = @"15101031041";
    
        CNContactStore *contactStore = [[CNContactStore alloc] init];
    
        //初始化单个联系人,注意一定是可变的,不可变的属性是只读的
        CNMutableContact *contact = [[CNMutableContact alloc] init];
        contact.familyName        = name;
        //封装电话号码
        CNPhoneNumber *phoneNumber   = [CNPhoneNumber phoneNumberWithStringValue:phone];
        CNLabeledValue *labeledValue = [[CNLabeledValue alloc] initWithLabel:@"手机号码" value:phoneNumber];
        NSArray *array               = @[labeledValue];
        contact.phoneNumbers         = array;
        //将请求封装成saveRequest
        CNSaveRequest *saveRequest   = [[CNSaveRequest alloc] init];
        //添加单个联系人
        [saveRequest addContact:contact toContainerWithIdentifier:nil];
        NSError *error = nil;
        //执行请求
        [contactStore executeSaveRequest:saveRequest error:&error];
        NSLog(@"添加联系人成功");
    }
    

    删除联系人

    - (void)deletePeople {
        CNContactStore *contactStore = [[CNContactStore alloc] init];
        for (CNContact *contact in allContacts) {
            NSString *familyNameString = contact.familyName;
            NSString *givenNameString  = contact.givenName;
            NSString *nameString = [familyNameString stringByAppendingString:givenNameString];
            
            if ([nameString isEqualToString:@"沙僧"]) {
                CNSaveRequest *deleteRequest = [[CNSaveRequest alloc] init];
                [deleteRequest deleteContact:contact];
    
                NSError *error = nil;
                [contactStore executeSaveRequest:deleteRequest error:&error];
                NSLog(@"删除联系人成功");
            }
        }
    }
    

    注:
    1、由于不同系统、设备等情况下获取的电话号码信息中会存在各种各样的连接符/分隔符,在使用时需要去除/格式化这部分信息。
    2、方法执行优先级的看法:列表选中响应和详情选中响应的两个方法不存在优先级的关系,响应了列表选中方法之后,就没有机会再进入详情页,也就不会再响应详情。
    3、ABPerson.h中有AddressBook.framework 和Contacts.framework属性之间的对应关系。

    相关文章

      网友评论

          本文标题:系统通讯录的使用之基于 Contacts.framework 和

          本文链接:https://www.haomeiwen.com/subject/whappxtx.html