ios開發 之 通訊錄操作


原文地址:http://blog.csdn.net/zeng_zhiming/article/details/70141316


在ios開發中,  通訊錄操作還是比較常見的, 尤其是在社交項目中更爲突出.  目前系統提供了兩個框架對通訊錄進行操作:


1. 兼容iOS9以前的框架

#import <AddressBook/AddressBook.h>

2.iOS9以後的新框架

#import <ContactsUI/ContactsUI.h>


爲了項目能兼容老版本, 本文主要整理<AddressBook>的使用:


一.  判斷通訊錄權限

    // 判斷權限
    switch (ABAddressBookGetAuthorizationStatus()) {
        case kABAuthorizationStatusNotDetermined:   //!< 未選擇權限.
        {

        }
            break;
        case kABAuthorizationStatusRestricted:      //!< 權限被限制.
        {

        }
            break;
        case kABAuthorizationStatusDenied:          //!< 已拒絕權限.
        {

        }
            break;
        case kABAuthorizationStatusAuthorized:      //!< 已授權.
        {

        }
            break;
            
        default:
            break;
    }

二. 請求通訊錄訪問權限

/**
 請求通訊錄訪問權限

 @param completion 權限回調
 */
- (void)requestAddressBookAccessWithCompletion:(void (^)(int code, NSString *msg))completion
{
    // 請求訪問用戶通訊錄,注意無論成功與否block都會調用
    ABAddressBookRequestAccessWithCompletion(_addressBook, ^(bool granted, CFErrorRef error) {
        // 回調到主線程返回結果
        dispatch_async(dispatch_get_main_queue(), ^{
            if (granted) {
                if (completion) completion(1, @"請求通訊錄訪問權限成功");
            } else {
                if (completion) completion(-1, @"請求通訊錄訪問權限失敗");
            }
        });
    });
}


三.  通訊錄操作

1.  獲取通訊錄聯繫人列表

/**
 *  同步獲取通訊錄聯繫人列表
 *
 *  @return 通訊錄ZMPersonModel數組
 */
- (NSArray<ZMPersonModel *> *)getAddressBookPersonListWithSort:(PersonSort)personSort
{
    // 檢測權限
    if (ABAddressBookGetAuthorizationStatus() != kABAuthorizationStatusAuthorized) {
        return nil;
    }

    // 按照排序讀取所有聯繫人
    CFArrayRef allPerson = NULL;
    switch (personSort) {
        case SortByFirstName:   //!< 名字排序.
            allPerson = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(_addressBook, kABSourceTypeLocal, kABPersonSortByFirstName);
            break;
        case SortByLastName:    //!< 姓氏排序.
            allPerson = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(_addressBook, kABSourceTypeLocal, kABPersonSortByLastName);
            break;
        case SortByCreationTime://!< 創建時間排序.
        default:
            allPerson = ABAddressBookCopyArrayOfAllPeople(_addressBook);
            break;
    }
    
    // 存儲通訊錄的數組
    NSMutableArray<ZMPersonModel *> *addressBookArray = [NSMutableArray array];

    // 循環遍歷,獲取每個聯繫人信息
    for (NSInteger i = 0; i < CFArrayGetCount(allPerson); i++)  {
        ABRecordRef person = CFArrayGetValueAtIndex(allPerson, i);
        ZMPersonModel *personModel =  [[ZMPersonModel alloc] initWithPerson:person];
        [addressBookArray addObject:personModel];
    }
    
    // 釋放資源
    if (allPerson) CFRelease(allPerson);
    
    return addressBookArray;
}

2. 根據RecordID查找聯繫人

/**
 根據RecordID查找聯繫人

 @param recordID 聯繫人ID
 @return ZMPersonModel對象
 */
- (ZMPersonModel *)getPersonWithRecordID:(ABRecordID)recordID
{
    // 獲取Person
    ABRecordRef person = ABAddressBookGetPersonWithRecordID(_addressBook, recordID);
    
    // 初始化爲ZMPersonModel
    ZMPersonModel *personModel = [[ZMPersonModel alloc] initWithPerson:person];
    
    return personModel;
}

3. 根據Name查找聯繫人

/**
 根據Name查找聯繫人

 @param name 查找關鍵字
 @return ZMPersonModel數組
 */
- (NSArray<ZMPersonModel *> *)getPersonsWithName:(NSString *)name
{
    // 空值過濾
    if (name == nil || name.length == 0) {
        return nil;
    }
    
    // 根據Name獲取聯繫人
    CFArrayRef persons =  ABAddressBookCopyPeopleWithName(_addressBook, (__bridge CFStringRef)(name));

    // 存儲通訊錄的數組
    NSMutableArray<ZMPersonModel *> *personArray = [NSMutableArray array];
    
    // 循環遍歷,獲取每個聯繫人信息
    for (NSInteger i = 0; i < CFArrayGetCount(persons); i++)  {
        ABRecordRef person = CFArrayGetValueAtIndex(persons, i);
        ZMPersonModel *personModel =  [[ZMPersonModel alloc] initWithPerson:person];
        [personArray addObject:personModel];
    }
    
    // 釋放資源
    if (persons) CFRelease(persons);

    return personArray;
}

4. 添加聯繫到通訊錄

/**
 批量添加聯繫到通訊錄
 
 @param personArray ZMPersonModel數組
 @return 添加結果
 */
- (BOOL)addPersons:(NSArray<ZMPersonModel *> *)personArray
{
    // 空值過濾
    if (personArray == nil || personArray.count == 0) {
        return NO;
    }
    
    // 添加結果
    BOOL result = YES;
    
    // 遍歷數組將聯繫人添加到通訊錄中
    for (ZMPersonModel *personModel in personArray)
    {
        // 實例化CFErrorRef
        CFErrorRef errorRef = NULL;
        
        // 添加聯繫人
        if (ABAddressBookAddRecord(_addressBook, [personModel getRecordRef], &errorRef) == true) {
            // 保存通訊錄
            if (!ABAddressBookSave(_addressBook, &errorRef)) {
                result = NO;
            }
        }
        
        // 錯誤消息處理
        if (errorRef) {
            NSLog(@"Add Person Error:%@", errorRef);
            CFRelease(errorRef);
        }
    }

    return result;
}

5. 修改聯繫人

/**
 更新聯繫人
 
 @param personModel ZMPersonModel對象
 @return 更新結果
 */
- (BOOL)updatePerson:(ZMPersonModel *)personModel
{
    BOOL result = NO;
    
    // 空值過濾
    if (personModel == nil) {
        return result;
    }
    
    // 實例化CFErrorRef
    CFErrorRef errorRef = NULL;
    
    // 獲取Person
    ABRecordRef person = ABAddressBookGetPersonWithRecordID(_addressBook, personModel.recordID);
    
    // 將Model中數據更新到person中
    if ([personModel updateToRecordRef:person]) {
        // 保存通訊錄
        result = ABAddressBookSave(_addressBook, &errorRef);
    }

    // 錯誤消息處理
    if (errorRef) {
        NSLog(@"Add Person Error:%@", errorRef);
        CFRelease(errorRef);
    }
    
    return result;
}

6. 刪除聯繫人

/**
 根據RecordID刪除聯繫人

 @param recordID 聯繫人ID
 @return 刪除結果
 */
- (BOOL)removePersonWithRecordID:(ABRecordID)recordID
{
    BOOL result = NO;
    
    // 實例化CFErrorRef
    CFErrorRef errorRef = NULL;
    
    // 獲取Person
    ABRecordRef person = ABAddressBookGetPersonWithRecordID(_addressBook, recordID);
    if ((person != NULL) && ABAddressBookRemoveRecord(_addressBook, person, &errorRef)) {
        // 保存通訊錄
        if (ABAddressBookSave(_addressBook, &errorRef)) {
            result = YES;
        }
    }

    // 錯誤消息處理
    if (errorRef) {
        NSLog(@"Remove Person Error:%@", errorRef);
        CFRelease(errorRef);
    }
    
    return result;
}

四. 聯繫人數據解析

1. 解析聯繫人所以數據

/**
 設置屬性值
 */
- (void)setValueWithPerson:(ABRecordRef)person
{
    // 空值過濾
    if (person == NULL) {
        return;
    }
    
    /** 獲取RecordID */
    _recordID = ABRecordGetRecordID(person);
    
    /** 姓名相關 */
    _firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));  //!< 名字.
    _lastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));    //!< 姓氏.
    _middleName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonMiddleNameProperty));//!< 中間名.
    _prefix = CFBridgingRelease(ABRecordCopyValue(person, kABPersonPrefixProperty));        //!< 前綴.
    _suffix = CFBridgingRelease(ABRecordCopyValue(person, kABPersonSuffixProperty));        //!< 後綴.
    _nickname = CFBridgingRelease(ABRecordCopyValue(person, kABPersonNicknameProperty));    //!< 暱稱.
    _firstNamePhonetic = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNamePhoneticProperty));  //!< 名字拼音或音標.
    _lastNamePhonetic = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNamePhoneticProperty));    //!< 姓氏拼音或音標.
    _middleNamePhonetic = CFBridgingRelease(ABRecordCopyValue(person, kABPersonMiddleNamePhoneticProperty));//!< 中間名拼音或音標.
    
    /** 工作相關 */
    _organization =  CFBridgingRelease(ABRecordCopyValue(person, kABPersonOrganizationProperty));   //!< 公司名稱.
    _department =  CFBridgingRelease(ABRecordCopyValue(person, kABPersonDepartmentProperty));       //!< 部門.
    _jobTitle =  CFBridgingRelease(ABRecordCopyValue(person, kABPersonJobTitleProperty));           //!< 職位.
    
    /** 備註 */
    _note =  CFBridgingRelease(ABRecordCopyValue(person, kABPersonNoteProperty));                   //!< 備註.
    
    /** 日期相關 */
    _birthday =  CFBridgingRelease(ABRecordCopyValue(person, kABPersonBirthdayProperty));                //!< 生日.
    _creationDate = CFBridgingRelease(ABRecordCopyValue(person, kABPersonCreationDateProperty));         //!< 創建時間.
    _modificationDate = CFBridgingRelease(ABRecordCopyValue(person, kABPersonModificationDateProperty)); //!< 最近修改時間.
    
    /** 農曆生日 */
    
    NSDictionary *brithdayDict = CFBridgingRelease(ABRecordCopyValue(person, kABPersonAlternateBirthdayProperty));
    if (!IsNullDictionary(brithdayDict))
    {
        ZMAlternateBirthdayModel *brithdayModel = [[ZMAlternateBirthdayModel alloc] init];
        // 標誌
        brithdayModel.calendar = [brithdayDict valueForKey:(NSString *)kABPersonAlternateBirthdayCalendarIdentifierKey];
        // 紀元
        brithdayModel.era = [[brithdayDict valueForKey:(NSString *)kABPersonAlternateBirthdayEraKey] integerValue];
        // 年份
        brithdayModel.year = [[brithdayDict valueForKey:(NSString *)kABPersonAlternateBirthdayYearKey] integerValue];
        // 月份
        brithdayModel.month = [[brithdayDict valueForKey:(NSString *)kABPersonAlternateBirthdayMonthKey] integerValue];
        // 日期
        brithdayModel.day = [[brithdayDict valueForKey:(NSString *)kABPersonAlternateBirthdayDayKey] integerValue];
        // 是否閏月
        brithdayModel.leapMonth = [[brithdayDict valueForKey:(NSString *)kABPersonAlternateBirthdayIsLeapMonthKey] boolValue];
    
        _alternateBirthday = brithdayModel;
    }
    
    
    /** 分類 */
    CFNumberRef kindType = ABRecordCopyValue(person, kABPersonKindProperty);
    _kind = (kindType == kABPersonKindOrganization) ? KindOrganization : KindPerson;
    if (kindType != NULL) CFRelease(kindType);
    
    /** 頭像 */
    if (ABPersonHasImageData(person) == true) {
        // 獲得頭像原圖
        NSData *imageData = CFBridgingRelease(ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatOriginalSize));
        _headImage = [UIImage imageWithData:imageData];
    }
    
    /** 電子郵件列表 */
    NSMutableArray<ZMLabelStringModel *> *emailArray = [NSMutableArray array];
    ABMultiValueRef emailRef = ABRecordCopyValue(person, kABPersonEmailProperty);
    for (int i = 0; i < ABMultiValueGetCount(emailRef); i++)
    {
        ZMLabelStringModel *emailModel = [[ZMLabelStringModel alloc] init];
        // 標籤
        emailModel.label    = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(emailRef, i));;
        // 郵箱地址
        emailModel.content  = CFBridgingRelease(ABMultiValueCopyValueAtIndex(emailRef, i));
        // 添加到數組
        [emailArray addObject:emailModel];
    }
    if (emailRef) CFRelease(emailRef);
    _emails = emailArray;
    
    /** 地址列表 */
    NSMutableArray<ZMAddressModel *> *addressArray = [NSMutableArray array];
    ABMultiValueRef addressRef = ABRecordCopyValue(person, kABPersonAddressProperty);
    for(int i = 0; i < ABMultiValueGetCount(addressRef); i++)
    {
        ZMAddressModel *addressModel = [[ZMAddressModel alloc] init];
        // 標籤
        addressModel.label = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(addressRef, i));
        // 獲取地址字典
        NSDictionary *addressDict = CFBridgingRelease(ABMultiValueCopyValueAtIndex(addressRef, i));
        if (!IsNullDictionary(addressDict)) {
            // 街道
            addressModel.street      = [addressDict valueForKey:(NSString *)kABPersonAddressStreetKey];
            // 城市
            addressModel.city        = [addressDict valueForKey:(NSString *)kABPersonAddressCityKey];
            // 省
            addressModel.state       = [addressDict valueForKey:(NSString *)kABPersonAddressStateKey];
            // 郵政編碼
            addressModel.zip         = [addressDict valueForKey:(NSString *)kABPersonAddressZIPKey];
            // 國家
            addressModel.country     = [addressDict valueForKey:(NSString *)kABPersonAddressCountryKey];
            // 國別碼
            addressModel.countryCode = [addressDict valueForKey:(NSString *)kABPersonAddressCountryCodeKey];
        }
        // 添加到數組
        [addressArray addObject:addressModel];
    }
    if (addressRef) CFRelease(addressRef);
    _addresses = addressArray;
    
    /** 日期列表 */
    NSMutableArray <ZMLabelDateModel *> *dateArray = [NSMutableArray array];
    ABMultiValueRef dateRef = ABRecordCopyValue(person, kABPersonDateProperty);
    for (int i = 0; i < ABMultiValueGetCount(dateRef); i++)
    {
        ZMLabelDateModel *dateModel = [[ZMLabelDateModel alloc] init];
        // 標籤
        dateModel.label = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(dateRef, i));
        // 日期
        dateModel.date  = CFBridgingRelease(ABMultiValueCopyValueAtIndex(dateRef, i));
        // 添加到數組
        [dateArray addObject:dateModel];
    }
    if (dateRef) CFRelease(dateRef);
    _dates = dateArray;
    
    /** 電話列表 */
    NSMutableArray<ZMLabelStringModel *> *phoneArray = [NSMutableArray array];
    ABMultiValueRef phoneRef = ABRecordCopyValue(person, kABPersonPhoneProperty);
    for (int i = 0; i < ABMultiValueGetCount(phoneRef); i++)
    {
        ZMLabelStringModel *phoneModel = [[ZMLabelStringModel alloc] init];
        // 標籤
        phoneModel.label = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(phoneRef, i));
        // 電話號碼
        phoneModel.content = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phoneRef, i));
        // 添加到數組
        [phoneArray addObject:phoneModel];
    }
    if (phoneRef) CFRelease(phoneRef);
    _phones = phoneArray;
    
    /** 即時信息列表 */
    NSMutableArray<ZMInstantMessageModel *> *instantMessageArray = [NSMutableArray array];
    ABMultiValueRef instantMessageRef = ABRecordCopyValue(person, kABPersonInstantMessageProperty);
    for (int i = 1; i < ABMultiValueGetCount(instantMessageRef); i++)
    {
        ZMInstantMessageModel *instantMessageModel = [[ZMInstantMessageModel alloc] init];
        // 標籤
        instantMessageModel.label = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(instantMessageRef, i));
        // 獲取即時信息字典
        NSDictionary *instantMessageDict = CFBridgingRelease(ABMultiValueCopyValueAtIndex(instantMessageRef, i));
        if (!IsNullDictionary(instantMessageDict)) {
            // 服務賬號
            instantMessageModel.username = [instantMessageDict valueForKey:(NSString *)kABPersonInstantMessageUsernameKey];
            // 服務名稱
            instantMessageModel.service = [instantMessageDict valueForKey:(NSString *)kABPersonInstantMessageServiceKey];
        }
        // 添加到數組
        [instantMessageArray addObject:instantMessageModel];
    }
    if (instantMessageRef) CFRelease(instantMessageRef);
    _instantMessages = instantMessageArray;
    
    /** URL列表 */
    NSMutableArray<ZMLabelStringModel *> *urlArray = [NSMutableArray array];
    ABMultiValueRef urlRef = ABRecordCopyValue(person, kABPersonURLProperty);
    for (int i = 0; i < ABMultiValueGetCount(urlRef); i++)
    {
        ZMLabelStringModel *urlModel = [[ZMLabelStringModel alloc] init];
        // 標籤
        urlModel.label = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(urlRef,i));
        // URL地址
        urlModel.content = CFBridgingRelease(ABMultiValueCopyValueAtIndex(urlRef,i));
        // 添加到數組
        [urlArray addObject:urlModel];
    }
    if (urlRef) CFRelease(urlRef);
    _urls = urlArray;
    
    /** 關聯人列表 */
    NSMutableArray<ZMLabelStringModel *> *relatedNameArray = [NSMutableArray array];
    ABMultiValueRef relatedNameRef = ABRecordCopyValue(person, kABPersonRelatedNamesProperty);
    for (int i = 0; i < ABMultiValueGetCount(relatedNameRef); i++)
    {
        ZMLabelStringModel *relatedNameModel = [[ZMLabelStringModel alloc] init];
        // 標籤
        relatedNameModel.label = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(relatedNameRef, i));
        // 關聯人姓名
        relatedNameModel.content = CFBridgingRelease(ABMultiValueCopyValueAtIndex(relatedNameRef, i));
        // 添加到數組
        [relatedNameArray addObject:relatedNameModel];
    }
    if (relatedNameRef) CFRelease(relatedNameRef);
    _relatedNames = relatedNameArray;
    
    /** 社交資料列表 */
    NSMutableArray<ZMSocialProfileModel *> *socialProfileArray = [NSMutableArray array];
    ABMultiValueRef socialProfileRef = ABRecordCopyValue(person, kABPersonSocialProfileProperty);
    for (int i = 0 ; i < ABMultiValueGetCount(socialProfileRef); i++)
    {
        // 獲取社交資料字典
        NSDictionary *socialProfileDict = CFBridgingRelease(ABMultiValueCopyValueAtIndex(socialProfileRef, i));
        if (!IsNullDictionary(socialProfileDict)) {
            ZMSocialProfileModel *socialProfileModel = [[ZMSocialProfileModel alloc] init];
            // 社交鏈接
            socialProfileModel.url = [socialProfileDict valueForKey:(NSString *)kABPersonSocialProfileURLKey];
            // 服務名稱
            socialProfileModel.service = [socialProfileDict valueForKey:(NSString *)kABPersonSocialProfileServiceKey];
            // 社交服務賬號
            socialProfileModel.username = [socialProfileDict valueForKey:(NSString *)kABPersonSocialProfileUsernameKey];
            // 用戶標識
            socialProfileModel.userIdentifier = [socialProfileDict valueForKey:(NSString *)kABPersonSocialProfileUserIdentifierKey];
            // 添加到數組
            [socialProfileArray addObject:socialProfileModel];
        }
    }
    if (socialProfileRef) CFRelease(socialProfileRef);
    _socialProfiles = socialProfileArray;
}

2. 生成聯繫所有數據

/**
 將Model數據賦值到ABRecordRef
 
 @param person ABRecordRef對象
 @return 賦值結果
 */
- (BOOL)updateToRecordRef:(ABRecordRef)person
{
    // 空值處理
    if (person == NULL) {
        return NO;
    }
    
    // 實例化CFErrorRef
    CFErrorRef errorRef = NULL;
    
    /** 姓名相關 */
    ABRecordSetValue(person, kABPersonFirstNameProperty, (__bridge CFStringRef)(_firstName), &errorRef);  //!< 名字.
    ABRecordSetValue(person, kABPersonLastNameProperty, (__bridge CFStringRef)(_lastName), &errorRef);    //!< 姓氏.
    ABRecordSetValue(person, kABPersonMiddleNameProperty, (__bridge CFStringRef)(_middleName), &errorRef);//!< 中間名.
    ABRecordSetValue(person, kABPersonPrefixProperty, (__bridge CFStringRef)(_prefix), &errorRef);        //!< 前綴.
    ABRecordSetValue(person, kABPersonSuffixProperty, (__bridge CFStringRef)(_suffix), &errorRef);        //!< 後綴.
    ABRecordSetValue(person, kABPersonNicknameProperty, (__bridge CFStringRef)(_nickname), &errorRef);    //!< 暱稱.
    ABRecordSetValue(person, kABPersonFirstNamePhoneticProperty, (__bridge CFStringRef)(_firstNamePhonetic), &errorRef);  //!< 名字拼音或音標.
    ABRecordSetValue(person, kABPersonLastNamePhoneticProperty, (__bridge CFStringRef)(_lastNamePhonetic), &errorRef);    //!< 姓氏拼音或音標.
    ABRecordSetValue(person, kABPersonMiddleNamePhoneticProperty, (__bridge CFStringRef)(_middleNamePhonetic), &errorRef);//!< 中間名拼音或音標.
    
    /** 工作相關 */
    ABRecordSetValue(person, kABPersonOrganizationProperty, (__bridge CFStringRef)(_organization), &errorRef);//!< 公司名稱.
    ABRecordSetValue(person, kABPersonDepartmentProperty, (__bridge CFStringRef)(_department), &errorRef);    //!< 部門.
    ABRecordSetValue(person, kABPersonJobTitleProperty, (__bridge CFStringRef)(_jobTitle), &errorRef);        //!< 職位.
    
    /** 備註 */
    ABRecordSetValue(person, kABPersonNoteProperty, (__bridge CFStringRef)(_note), &errorRef);                //!< 備註.
    
    /** 日期相關 */
    ABRecordSetValue(person, kABPersonBirthdayProperty, (__bridge CFDateRef)(_birthday), &errorRef);                //!< 生日.
    ABRecordSetValue(person, kABPersonCreationDateProperty, (__bridge CFDateRef)(_creationDate), &errorRef);        //!< 創建時間.
    ABRecordSetValue(person, kABPersonModificationDateProperty, (__bridge CFDateRef)(_modificationDate), &errorRef);//!< 最近修改時間.
    
    /** 農曆生日 */
    if (_alternateBirthday)
    {
        NSMutableDictionary *brithdayDict = [NSMutableDictionary dictionary];
        // 標誌
        brithdayDict[(NSString *)kABPersonAlternateBirthdayCalendarIdentifierKey] = _alternateBirthday.calendar;
        // 紀元
        brithdayDict[(NSString *)kABPersonAlternateBirthdayEraKey] = @(_alternateBirthday.era);
        // 年份
        brithdayDict[(NSString *)kABPersonAlternateBirthdayYearKey] = @(_alternateBirthday.year);
        // 月份
        brithdayDict[(NSString *)kABPersonAlternateBirthdayMonthKey] = @(_alternateBirthday.month);
        // 日期
        brithdayDict[(NSString *)kABPersonAlternateBirthdayDayKey] = @(_alternateBirthday.day);
        // 是否閏月
        brithdayDict[(NSString *)kABPersonAlternateBirthdayIsLeapMonthKey] = @(_alternateBirthday.leapMonth);
        
        ABRecordSetValue(person, kABPersonAlternateBirthdayProperty, (__bridge CFDictionaryRef)(brithdayDict), &errorRef);
    }
    
    /** 分類 */
    CFNumberRef personKind = (_kind == KindOrganization) ? kABPersonKindOrganization : kABPersonKindPerson;
    ABRecordSetValue(person, kABPersonKindProperty, personKind, &errorRef);
    
    /** 頭像 */
    if (_headImage) {
        NSData *imageData = UIImagePNGRepresentation(_headImage);
        ABPersonSetImageData(person, (__bridge CFDataRef)(imageData),&errorRef);
    }
    
    /** 電子郵件列表 */
    ABMultiValueRef emailRef = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    for (ZMLabelStringModel *emailModel in _emails) {
        ABMultiValueAddValueAndLabel(emailRef, (__bridge CFStringRef)(emailModel.content), (__bridge CFStringRef)(emailModel.label), NULL);
    }
    ABRecordSetValue(person, kABPersonEmailProperty, emailRef, &errorRef);
    if (emailRef) CFRelease(emailRef);
    
    /** 地址列表 */
    ABMultiValueRef addressRef = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
    for (ZMAddressModel *addressModel in _addresses)
    {
        NSMutableDictionary *addressDict = [NSMutableDictionary dictionary];
        // 街道
        addressDict[(NSString *)kABPersonAddressStreetKey] = addressModel.street;
        // 城市
        addressDict[(NSString *)kABPersonAddressCityKey] = addressModel.city;
        // 省
        addressDict[(NSString *)kABPersonAddressStateKey] = addressModel.state;
        // 郵政編碼
        addressDict[(NSString *)kABPersonAddressZIPKey] = addressModel.zip;
        // 國家
        addressDict[(NSString *)kABPersonAddressCountryKey] = addressModel.country;
        // 國別碼
        addressDict[(NSString *)kABPersonAddressCountryCodeKey] = addressModel.countryCode;
        
        ABMultiValueAddValueAndLabel(addressRef, (__bridge CFDictionaryRef)(addressDict), (__bridge CFStringRef)addressModel.label, NULL);
    }
    ABRecordSetValue(person, kABPersonAddressProperty, addressRef, &errorRef);
    if (addressRef) CFRelease(addressRef);
    
    /** 日期列表 */
    ABMultiValueRef dateRef = ABMultiValueCreateMutable(kABMultiDateTimePropertyType);
    for (ZMLabelDateModel *dateModel in _dates) {
        ABMultiValueAddValueAndLabel(dateRef, (__bridge CFDateRef)(dateModel.date), (__bridge CFStringRef)(dateModel.label), NULL);
    }
    ABRecordSetValue(person, kABPersonDateProperty, dateRef, &errorRef);
    if (dateRef) CFRelease(dateRef);
    
    /** 電話列表 */
    ABMultiValueRef phoneRef = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    for (ZMLabelStringModel *phoneModel in _phones) {
        ABMultiValueAddValueAndLabel(phoneRef, (__bridge CFStringRef)(phoneModel.content), (__bridge CFStringRef)(phoneModel.label), NULL);
    }
    ABRecordSetValue(person, kABPersonPhoneProperty, phoneRef, &errorRef);
    if (phoneRef) CFRelease(phoneRef);
    
    /** 即時信息列表 */
    ABMultiValueRef instantMessageRef = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
    for (ZMInstantMessageModel *instantMessageModel in _instantMessages)
    {
        NSMutableDictionary *instantMessageDict = [NSMutableDictionary dictionary];
        // 服務賬號
        instantMessageDict[(NSString *)kABPersonInstantMessageUsernameKey] = instantMessageModel.username;
        // 服務名稱
        instantMessageDict[(NSString *)kABPersonInstantMessageServiceKey] = instantMessageModel.service;
        
        ABMultiValueAddValueAndLabel(instantMessageRef, (__bridge CFDictionaryRef)(instantMessageDict), (__bridge CFStringRef)instantMessageModel.label, NULL);
    }
    ABRecordSetValue(person, kABPersonInstantMessageProperty, instantMessageRef, &errorRef);
    if (instantMessageRef) CFRelease(instantMessageRef);
    
    /** URL列表 */
    ABMultiValueRef urlRef = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    for (ZMLabelStringModel *urlModel in _urls) {
        ABMultiValueAddValueAndLabel(urlRef, (__bridge CFStringRef)(urlModel.content), (__bridge CFStringRef)(urlModel.label), NULL);
    }
    ABRecordSetValue(person, kABPersonURLProperty, urlRef, &errorRef);
    if (urlRef) CFRelease(urlRef);
    
    /** 關聯人列表 */
    ABMultiValueRef relatedNameRef = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    for (ZMLabelStringModel *relatedNameModel in _relatedNames) {
        ABMultiValueAddValueAndLabel(relatedNameRef, (__bridge CFStringRef)(relatedNameModel.content), (__bridge CFStringRef)(relatedNameModel.label), NULL);
    }
    ABRecordSetValue(person, kABPersonRelatedNamesProperty, relatedNameRef, &errorRef);
    if (relatedNameRef) CFRelease(relatedNameRef);
    
    /** 社交資料列表 */
    ABMultiValueRef socialProfileRef = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
    for (ZMSocialProfileModel *socialProfileModel in _socialProfiles)
    {
        NSMutableDictionary *socialProfileDict = [NSMutableDictionary dictionary];
        // 社交鏈接
        socialProfileDict[(NSString *)kABPersonSocialProfileURLKey] = socialProfileModel.url;
        // 服務名稱
        socialProfileDict[(NSString *)kABPersonSocialProfileServiceKey] = socialProfileModel.service;
        // 社交服務賬號
        socialProfileDict[(NSString *)kABPersonSocialProfileUsernameKey] = socialProfileModel.username;
        // 用戶標識
        socialProfileDict[(NSString *)kABPersonSocialProfileUserIdentifierKey] = socialProfileModel.userIdentifier;
        
        ABMultiValueAddValueAndLabel(socialProfileRef, (__bridge CFDictionaryRef)(socialProfileDict), NULL, NULL);
    }
    ABRecordSetValue(person, kABPersonSocialProfileProperty, socialProfileRef, &errorRef);
    if (socialProfileRef) CFRelease(socialProfileRef);
    
    // 錯誤消息處理
    if (errorRef) {
        NSLog(@"ZMPersonModel to RecordRef error:%@", errorRef);
        CFRelease(errorRef);
        return NO;
    }
    
    return YES;
}

五.  通訊錄改變監聽


1. 註冊通訊錄變動監聽

// 註冊通訊錄變動的回調
        ABAddressBookRegisterExternalChangeCallback(_addressBook, addressBookChangeCallBack, (__bridge_retained void *)(self));

2. 實現通訊錄變動監聽

/**
 通訊錄聯繫人變動的回調
 
 @param addressBook 註冊的addressBook
 @param info        變動之後進行的回調方法
 @param context     傳參,這裏是將自己作爲參數傳到方法中
 */
void addressBookChangeCallBack(ABAddressBookRef addressBook, CFDictionaryRef info, void *context)
{
    // 清除緩存,重置addressBook
    ABAddressBookRevert(addressBook);
    
}

3. 移除通訊錄變動監聽

// 移除監聽通訊錄變動的回調
    ABAddressBookUnregisterExternalChangeCallback(_addressBook, addressBookChangeCallBack, (__bridge void *)(self));

六. Demo展示

1. Demo效果圖



2. Demo下載: https://github.com/zeng-zhiming/ZMAddressBook




原文地址:http://blog.csdn.net/zeng_zhiming/article/details/70141316










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章