iOS通讯录(无界面)详解

关于通讯录的操作,系统提供了2个框架:
AddressBookUI.framework 主要提供了通讯录操作的相关界面API
AddressBook.framework 主要提供了与通讯录数据库交互的API

在iOS9.0以后系统新添加了Contacts.frameworkContactsUI.framework2个框架,这两个框架可以实现以上两个框架的所有功能。

接下来主要介绍AddressBook.framework和新添加的Contacts.framework框架

申请通讯录授权

#import

ABAddressBookRef addressRef = ABAddressBookCreateWithOptions(nil, nil);
ABAddressBookRequestAccessWithCompletion(addressRef, ^(bool granted, CFErrorRef error) {
    if (granted) {
        // 授权成功
    }else{
        // 授权失败
    }
});

执行以上代码后,系统会自动弹出提示框,让用户进行授权。如果用户拒绝,再次调用以上代码则不弹出提示框,只有在用户手机的设置中更改权限。

Contacts框架的实现
#import

CNContactStore * store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
    if (granted) {
        // 授权成功
    }else{
        // 授权失败
    }
}];

通讯录权限状态

通过以下函数获得通讯录权限状态

ABAddressBookGetAuthorizationStatus()

状态枚举如下

typedef CF_ENUM(CFIndex, ABAuthorizationStatus) {
    // 用户还没有决定是否授权你的程序进行访问
    kABAuthorizationStatusNotDetermined = 0,    // deprecated, use CNAuthorizationStatusNotDetermined
    // iOS设备上的家长控制或其它一些许可配置阻止程序与通讯录数据库进行交互
    kABAuthorizationStatusRestricted,           // deprecated, use CNAuthorizationStatusRestricted
    // 用户明确的拒绝了你的程序对通讯录的访问
    kABAuthorizationStatusDenied,               // deprecated, use CNAuthorizationStatusDenied
    // 用户已经授权给你的程序对通讯录进行访问
    kABAuthorizationStatusAuthorized            // deprecated, use CNAuthorizationStatusAuthorized
} AB_DEPRECATED("use CNAuthorizationStatus");
AB_EXTERN ABAuthorizationStatus ABAddressBookGetAuthorizationStatus(void) AB_DEPRECATED("use [CNContactStore authorizationStatusForEntityType:]");

Contacts框架的实现
CNAuthorizationStatus权限状态

CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusRestricted || status == CNAuthorizationStatusDenied) {
    // 未授权
    // do something... 
}
typedef NS_ENUM(NSInteger, CNAuthorizationStatus)
{
    /*! The user has not yet made a choice regarding whether the application may access contact data. */
    CNAuthorizationStatusNotDetermined = 0,
    /*! The application is not authorized to access contact data.
     *  The user cannot change this application’s status, possibly due to active restrictions such as parental controls being in place. */
    CNAuthorizationStatusRestricted,
    /*! The user explicitly denied access to contact data for the application. */
    CNAuthorizationStatusDenied,
    /*! The application is authorized to access contact data. */
    CNAuthorizationStatusAuthorized
} NS_ENUM_AVAILABLE(10_11, 9_0);

获取所有联系人

CFArrayRef dataArr = ABAddressBookCopyArrayOfAllPeople(addressRef);
for (int i = 0; i < CFArrayGetCount(dataArr); i ++) {
      
    ABRecordRef person = CFArrayGetValueAtIndex(dataArr, i);
    /*得到联系人对象,后续解析都是基于person对象进行操作*/
}

Contacts框架的实现

CNContactFetchRequest * request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]];
[store enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
    // block会不断调用...
    //(contact参数,在下文获取联系人各种属性中会用到)
}];

联系人属性以及获取

每个联系人对象都有很多属性,有的是单一属性,我们可以直接通过key来获取,像姓、名等。有的属性比较复杂可能需要我们进行多次解析才能获取到我们想要的值,比如多重属性:号码、邮件、地址等。
单一属性
对于单一属性我们可以这样直接获取:

// 姓
ABRecordCopyValue(person, kABPersonLastNameProperty);
// 名
ABRecordCopyValue(person, kABPersonFirstNameProperty);

ABRecordCopyValue()函数返回值是CFStringRef类型,我们可以通过桥接的方式转换NSString * str = (__bridge NSString *)(ABRecordCopyValue()),这里不讲解关于CoreFoundationFoundation桥接的知识。

// Property keys
/*名*/
AB_EXTERN const ABPropertyID kABPersonFirstNameProperty AB_DEPRECATED("use CNContact.givenName");                               // First name - kABStringPropertyType
/*姓*/
AB_EXTERN const ABPropertyID kABPersonLastNameProperty AB_DEPRECATED("use CNContact.familyName");                               // Last name - kABStringPropertyType
/*中间名*/
AB_EXTERN const ABPropertyID kABPersonMiddleNameProperty AB_DEPRECATED("use CNContact.middleName");                             // Middle name - kABStringPropertyType
/*前缀*/
AB_EXTERN const ABPropertyID kABPersonPrefixProperty AB_DEPRECATED("use CNContact.namePrefix");                                 // Prefix ("Sir" "Duke" "General") - kABStringPropertyType
/*后缀*/
AB_EXTERN const ABPropertyID kABPersonSuffixProperty AB_DEPRECATED("use CNContact.nameSuffix");                                 // Suffix ("Jr." "Sr." "III") - kABStringPropertyType
/*昵称*/
AB_EXTERN const ABPropertyID kABPersonNicknameProperty AB_DEPRECATED("use CNContact.nickname");                                 // Nickname - kABStringPropertyType
/*名字拼音或音标*/
AB_EXTERN const ABPropertyID kABPersonFirstNamePhoneticProperty AB_DEPRECATED("use CNContact.phoneticGivenName");               // First name Phonetic - kABStringPropertyType
/*姓氏拼音或音标*/
AB_EXTERN const ABPropertyID kABPersonLastNamePhoneticProperty AB_DEPRECATED("use CNContact.phoneticFamilyName");               // Last name Phonetic - kABStringPropertyType
/*中间名拼音或音标*/
AB_EXTERN const ABPropertyID kABPersonMiddleNamePhoneticProperty AB_DEPRECATED("use CNContact.phoneticMiddleName");             // Middle name Phonetic - kABStringPropertyType
/*公司*/
AB_EXTERN const ABPropertyID kABPersonOrganizationProperty AB_DEPRECATED("use CNContact.organizationName");                     // Company name - kABStringPropertyType
/*部门*/
AB_EXTERN const ABPropertyID kABPersonDepartmentProperty AB_DEPRECATED("use CNContact.departmentName");                         // Department name - kABStringPropertyType
/*职位*/
AB_EXTERN const ABPropertyID kABPersonJobTitleProperty AB_DEPRECATED("use CNContact.jobTitle");                                 // Job Title - kABStringPropertyType
/*生日*/
AB_EXTERN const ABPropertyID kABPersonBirthdayProperty AB_DEPRECATED("use CNContact.birthday");                                 // Birthday associated with this person - kABDateTimePropertyType
/*备注*/
AB_EXTERN const ABPropertyID kABPersonNoteProperty AB_DEPRECATED("use CNContact.note");                                         // Note - kABStringPropertyType
/*这条联系人信息的创建时间*/
AB_EXTERN const ABPropertyID kABPersonCreationDateProperty AB_DEPRECATED("");                                                   // Creation Date (when first saved)
/*这条联系人信息的最后保存时间*/
AB_EXTERN const ABPropertyID kABPersonModificationDateProperty AB_DEPRECATED("");                                               // Last saved date

Contacts框架的实现
在上文block中得到的contact对象,我们可以直接通过点语法获取相关属性。

// 姓
contact.familyName
// 名
contact.givenName

以上是获取姓氏、名字的方法,更多的属性可以对照上文中的ABPropertyID这里不再一一列举。
多重属性

  • 号码
// Phone numbers
AB_EXTERN const ABPropertyID kABPersonPhoneProperty AB_DEPRECATED("use CNContact.phoneNumbers");                                // Generic phone number - kABMultiStringPropertyType

/*手机*/
AB_EXTERN const CFStringRef kABPersonPhoneMobileLabel AB_DEPRECATED("use CNLabelPhoneNumberMobile");
/*iPhone*/
AB_EXTERN const CFStringRef kABPersonPhoneIPhoneLabel AB_DEPRECATED("use CNLabelPhoneNumberiPhone");
/*主要*/
AB_EXTERN const CFStringRef kABPersonPhoneMainLabel AB_DEPRECATED("use CNLabelPhoneNumberMain");
/*住宅*/
AB_EXTERN const CFStringRef kABPersonPhoneHomeFAXLabel AB_DEPRECATED("use CNLabelPhoneNumberHomeFax");
/*工作*/
AB_EXTERN const CFStringRef kABPersonPhoneWorkFAXLabel AB_DEPRECATED("use CNLabelPhoneNumberWorkFax");
/*其他*/
AB_EXTERN const CFStringRef kABPersonPhoneOtherFAXLabel AB_DEPRECATED("use CNLabelPhoneNumberOtherFax");
/**/
AB_EXTERN const CFStringRef kABPersonPhonePagerLabel AB_DEPRECATED("use CNLabelPhoneNumberPager");
ABMultiValueRef phoneNos = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSArray* phoneNosArr = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(phoneNos));
for(int i = 0; i< phoneNosArr.count; i++){
    // 号码类型(包括:住宅、工作、iPhone、手机、主要、住宅传真、工作传真、传呼、其他)
    NSString * phoneNoLabel = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(phoneNos, i));
    // 号码
    NSString * phoneNo = [phoneNosArr objectAtIndex:i];
    NSLog(@"-PhoneNo--%@:%@-",phoneNoLabel,phoneNo);
}
  • 邮件
/*邮件*/
AB_EXTERN const ABPropertyID kABPersonEmailProperty AB_DEPRECATED("use CNContact.emailAddresses");                              // Email(s) - kABMultiStringPropertyType
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);        
NSArray* emailsArr = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(emails));
for(int i = 0; i< emailsArr.count; i++){
    // 邮件类型(包括:住宅、工作、iCloud、其他)
    NSString * emailLabel = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(emails, i));
    // 邮件地址  
    NSString * email = [emailsArr objectAtIndex:i];    
    NSLog(@"-email--%@:%@-",emailLabel,email);
}
  • 地址
// Addresses
AB_EXTERN const ABPropertyID kABPersonAddressProperty AB_DEPRECATED("use CNContact.postalAddresses");                           // Street address - kABMultiDictionaryPropertyType

/*街道*/
AB_EXTERN const CFStringRef kABPersonAddressStreetKey AB_DEPRECATED("use CNPostalAddress.street");
/*城市*/
AB_EXTERN const CFStringRef kABPersonAddressCityKey AB_DEPRECATED("use CNPostalAddress.city");
/*省份、州*/
AB_EXTERN const CFStringRef kABPersonAddressStateKey AB_DEPRECATED("use CNPostalAddress.state");
/*邮政编码*/
AB_EXTERN const CFStringRef kABPersonAddressZIPKey AB_DEPRECATED("use CNPostalAddress.postalCode");
/*国家*/
AB_EXTERN const CFStringRef kABPersonAddressCountryKey AB_DEPRECATED("use CNPostalAddress.country");
/*国家编码*/
AB_EXTERN const CFStringRef kABPersonAddressCountryCodeKey AB_DEPRECATED("use CNPostalAddress.ISOCountryCode");
ABMultiValueRef addresses = ABRecordCopyValue(person, kABPersonAddressProperty);
NSArray* addressesArr = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(addresses));
for(int i = 0; i< addressesArr.count; i++){
    // 地址类型(包括:住宅、工作、其他)
    NSString * addressLabel = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(addresses, i));
    // 地址(注意这里得到的是字典类型,其中包括了:City、Country、CountryCode、State、Street、ZIP等信息)
    NSDictionary * address = [addressesArr objectAtIndex:i];

    NSLog(@"-Address--%@:%@-",addressLabel,address);
}
  • 日期
// Dates
AB_EXTERN const ABPropertyID kABPersonDateProperty AB_DEPRECATED("use CNContact.dates");                                        // Dates associated with this person - kABMultiDatePropertyType

/* 纪念日*/
AB_EXTERN const CFStringRef kABPersonAnniversaryLabel AB_DEPRECATED("use CNLabelDateAnniversary");
ABMultiValueRef dates = ABRecordCopyValue(person, kABPersonDateProperty);
NSArray* datesArr = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(dates));
for(int i = 0; i< datesArr.count; i++){
    // 日期类型(包括:纪念日、其他)
    NSString * dateLabel = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(dates, i));
    // 日期
    NSString * date = [datesArr objectAtIndex:i];
    
    NSLog(@"-Date--%@:%@-",dateLabel,date);
}
  • 即时信息
// IM
AB_EXTERN const ABPropertyID kABPersonInstantMessageProperty AB_DEPRECATED("use CNContact.instantMessageAddresses");            // Instant Messaging - kABMultiDictionaryPropertyType
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceKey AB_DEPRECATED("use CNInstantMessageAddress.service");             // Service ("Yahoo", "Jabber", etc.)

/*Yahoo! Messenger*/
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceYahoo AB_DEPRECATED("use CNInstantMessageServiceYahoo");
/*Jabber*/
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceJabber AB_DEPRECATED("use CNInstantMessageServiceJabber");
/*MSN Messenger*/
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceMSN AB_DEPRECATED("use CNInstantMessageServiceMSN");
/*ICQ*/
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceICQ AB_DEPRECATED("use CNInstantMessageServiceICQ");
/*AIM*/
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceAIM AB_DEPRECATED("use CNInstantMessageServiceAIM");
/*QQ*/
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceQQ AB_DEPRECATED("use CNInstantMessageServiceQQ");
/*Google Talk*/
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceGoogleTalk AB_DEPRECATED("use CNInstantMessageServiceGoogleTalk");
/*Skype*/
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceSkype AB_DEPRECATED("use CNInstantMessageServiceSkype");
/*Facebook Messenger*/
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceFacebook AB_DEPRECATED("use CNInstantMessageServiceFacebook");
/*Gadu-Gadu*/
AB_EXTERN const CFStringRef kABPersonInstantMessageServiceGaduGadu AB_DEPRECATED("use CNInstantMessageServiceGaduGadu");
ABMultiValueRef IMs = ABRecordCopyValue(person, kABPersonInstantMessageProperty);
NSArray* IMsArr = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(IMs));
for(int i = 0; i< IMsArr.count; i++){
    // 即时信息类型(包括:QQ、Skype、MSN Messenger、Google Talk、Facebook Messenger、AIM、Yahoo! Messenger、ICQ、Jabber、Gadu-Gadu)
    NSString * IMLabel = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(IMs, i));
    // 即时信息账号(字典中包括:service、username)
    NSDictionary * IM = [IMsArr objectAtIndex:i];
    
    NSLog(@"-IM--%@:%@-",IMLabel,IM);
}
  • 关联人
// Related names
AB_EXTERN const ABPropertyID kABPersonRelatedNamesProperty AB_DEPRECATED("use CNContact.contactRelations");                     // Names - kABMultiStringPropertyType

/*父亲*/
AB_EXTERN const CFStringRef kABPersonFatherLabel AB_DEPRECATED("use CNLabelContactRelationFather");                             // Father
/*母亲*/
AB_EXTERN const CFStringRef kABPersonMotherLabel AB_DEPRECATED("use CNLabelContactRelationMother");                             // Mother
/*父母*/
AB_EXTERN const CFStringRef kABPersonParentLabel AB_DEPRECATED("use CNLabelContactRelationParent");                             // Parent
/*兄弟*/
AB_EXTERN const CFStringRef kABPersonBrotherLabel AB_DEPRECATED("use CNLabelContactRelationBrother");                           // Brother
/*姐妹*/
AB_EXTERN const CFStringRef kABPersonSisterLabel AB_DEPRECATED("use CNLabelContactRelationSister");                             // Sister
/*子女*/
AB_EXTERN const CFStringRef kABPersonChildLabel AB_DEPRECATED("use CNLabelContactRelationChild");                               // Child
/*朋友*/
AB_EXTERN const CFStringRef kABPersonFriendLabel AB_DEPRECATED("use CNLabelContactRelationFriend");                             // Friend
/*配偶*/
AB_EXTERN const CFStringRef kABPersonSpouseLabel AB_DEPRECATED("use CNLabelContactRelationSpouse");                             // Spouse
/*伴侣*/
AB_EXTERN const CFStringRef kABPersonPartnerLabel AB_DEPRECATED("use CNLabelContactRelationPartner");                           // Partner
/*助理*/
AB_EXTERN const CFStringRef kABPersonAssistantLabel AB_DEPRECATED("use CNLabelContactRelationAssistant");                       // Assistant
/*上司*/
AB_EXTERN const CFStringRef kABPersonManagerLabel AB_DEPRECATED("use CNLabelContactRelationManager");                           // Manager
   
ABMultiValueRef relations = ABRecordCopyValue(person, kABPersonRelatedNamesProperty);
NSArray* relationsArr = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(relations));
for(int i = 0; i< relationsArr.count; i++){
    // 关联人类型(包括:父亲、母亲、父母、兄弟、姐妹、子女、朋友、配偶、伴侣、助理、上司、其他)
    NSString * relationLabel = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(relations, i));
    // 关联人
    NSString * relation = [relationsArr objectAtIndex:i];
    
    NSLog(@"-Relation--%@:%@-",relationLabel,relation);
}
  • 个人资料
// Social Profile
AB_EXTERN const ABPropertyID kABPersonSocialProfileProperty AB_DEPRECATED("use CNContact.socialProfiles");                      // kABMultiDictionaryPropertyType
AB_EXTERN const CFStringRef kABPersonSocialProfileURLKey AB_DEPRECATED("use CNSocialProfile.urlString");                        // string representation of a url for the social profile
    // the following properties are optional
    AB_EXTERN const CFStringRef kABPersonSocialProfileServiceKey AB_DEPRECATED("use CNSocialProfile.service");                  // string representing the name of the service (Twitter, Facebook, LinkedIn, etc.)
    AB_EXTERN const CFStringRef kABPersonSocialProfileUsernameKey AB_DEPRECATED("use CNSocialProfile.username");                // string representing the user visible name
    AB_EXTERN const CFStringRef kABPersonSocialProfileUserIdentifierKey AB_DEPRECATED("use CNSocialProfile.userIdentifier");    // string representing the service specific identifier (optional)

/*Twitter*/
AB_EXTERN const CFStringRef kABPersonSocialProfileServiceTwitter AB_DEPRECATED("use CNSocialProfileServiceTwitter");
/*新浪微博*/
AB_EXTERN const CFStringRef kABPersonSocialProfileServiceSinaWeibo AB_DEPRECATED("use CNSocialProfileServiceSinaWeibo");
/*GameCenter*/
AB_EXTERN const CFStringRef kABPersonSocialProfileServiceGameCenter AB_DEPRECATED("use CNSocialProfileServiceGameCenter");
/*Facebook*/
AB_EXTERN const CFStringRef kABPersonSocialProfileServiceFacebook AB_DEPRECATED("use CNSocialProfileServiceFacebook");
/*Myspace*/
AB_EXTERN const CFStringRef kABPersonSocialProfileServiceMyspace AB_DEPRECATED("use CNSocialProfileServiceMySpace");
/*LinkedIn*/
AB_EXTERN const CFStringRef kABPersonSocialProfileServiceLinkedIn AB_DEPRECATED("use CNSocialProfileServiceLinkedIn");
/*Flickr*/
AB_EXTERN const CFStringRef kABPersonSocialProfileServiceFlickr AB_DEPRECATED("use CNSocialProfileServiceFlickr");
ABMultiValueRef socialProfiles = ABRecordCopyValue(person, kABPersonSocialProfileProperty);
NSArray* socialProfilesArr = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(socialProfiles));
for(int i = 0; i< socialProfilesArr.count; i++){
    // 个人资料类型(包括:新浪微博、Twitter、Facebook、Flickr、LinkedIn、MySpace)
    NSString * socialProfileLabel = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(socialProfiles, i));
    // 账号信息(字典中包括:service、url、username)
    NSDictionary * socialProfile = [socialProfilesArr objectAtIndex:i];
    
    NSLog(@"-SocialProfile--%@:%@-",socialProfileLabel,socialProfile);
}

Contacts框架对应属性

/*号码数组*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray*>               *phoneNumbers;
/*邮件数组*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray*>                    *emailAddresses;
/*邮政地址*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray*>             *postalAddresses;
/*url数组*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray*>                    *urlAddresses;
/*关联人数组*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray*>           *contactRelations;
/*个人资料数组*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray*>             *socialProfiles;
/*即时信息账号数组*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray*>     *instantMessageAddresses;

/*! @abstract The Gregorian birthday.
 *
 *  @description Only uses day, month and year components. Needs to have at least a day and a month.
 */
@property (copy, nullable, NS_NONATOMIC_IOSONLY) NSDateComponents *birthday;

/*! @abstract The alternate birthday (Lunisolar).
 *
 *  @description Only uses day, month, year and calendar components. Needs to have at least a day and a month. Calendar must be Chinese, Hebrew or Islamic.
 */
@property (copy, nullable, NS_NONATOMIC_IOSONLY) NSDateComponents *nonGregorianBirthday;

/*! @abstract Other Gregorian dates (anniversaries, etc).
 *
 *  @description Only uses day, month and year components. Needs to have at least a day and a month.
 */
@property (copy, NS_NONATOMIC_IOSONLY) NSArray*> *dates;

头像
判断是否有头像

if (ABPersonHasImageData(person) == YES) {
    NSLog(@"有头像");
}else{
    NSLog(@"无头像");
}

头像获取

CFDataRef imgRef = ABPersonCopyImageData(person);

头像设置

ABPersonSetImageData(person, imgRef, nil);

Contacts框架的实现
Contacts框架中对于联系人头像的操作通过CNContact对象的imageData属性进行操作

contact.imageData

头像设置的时候contact对象的类型要是CNMutableContact类型

添加联系人

// 创建一个联系人
ABRecordRef recordRef = ABPersonCreate();
// 设置属性
ABRecordSetValue(recordRef, kABPersonLastNameProperty, @"姓", nil);
ABRecordSetValue(recordRef, kABPersonFirstNameProperty, @"名", nil);
// 将新建的联系人添加到通讯录
ABAddressBookAddRecord(addressRef, recordRef, nil);
// 保存通讯录
ABAddressBookSave(addressRef, nil);

Contacts框架的实现

// 创建一个联系人
CNMutableContact * contact = [[CNMutableContact alloc] init];
// 设置属性
contact.familyName = @"姓1";
contact.givenName  = @"名1";
// 创建一个保存请求对象
CNSaveRequest * request = [[CNSaveRequest alloc] init];
[request addContact:contact toContainerWithIdentifier:nil];
// 保存到通讯录
[store executeSaveRequest:request error:nil];

以上的出错信息参数都设置为了nil,大家在实际应用的时候可以添加上,以便查看错误信息。

版权声明:出自MajorLMJ技术博客的原创作品 ,转载时必须注明出处及相应链接!

你可能感兴趣的:(iOS通讯录(无界面)详解)