iOS通讯录(无界面)详解

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

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

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

申请通讯录授权

#import <AddressBook/AddressBook.h>

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

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

Contacts框架的实现
#import <Contacts/Contacts.h>

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<CNLabeledValue<CNPhoneNumber*>*>               *phoneNumbers;
/*邮件数组*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray<CNLabeledValue<NSString*>*>                    *emailAddresses;
/*邮政地址*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray<CNLabeledValue<CNPostalAddress*>*>             *postalAddresses;
/*url数组*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray<CNLabeledValue<NSString*>*>                    *urlAddresses;
/*关联人数组*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray<CNLabeledValue<CNContactRelation*>*>           *contactRelations;
/*个人资料数组*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray<CNLabeledValue<CNSocialProfile*>*>             *socialProfiles;
/*即时信息账号数组*/
@property (copy, NS_NONATOMIC_IOSONLY) NSArray<CNLabeledValue<CNInstantMessageAddress*>*>     *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<CNLabeledValue<NSDateComponents*>*> *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技术博客的原创作品 ,转载时必须注明出处及相应链接!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,376评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 爱的宣言:说给宇宙的宣言: 这是一个精彩非凡的宇宙 这宇宙带给我所有美好的事物 这宇宙暗中协助我成就每一件事 我所...
    陈卓越阅读 359评论 0 1
  • 好久不写文字,越来越懒。一直看着别人的文字,没有自己的输出,惭愧。 今天傍晚看了这部电影,讲述2段真实的故事。茱莉...
    墨花月白阅读 282评论 0 0
  • 付出的真心不对等,所以比较伤心 我不再是那个每天写日记都会对明天充满希望的小女孩了,因为我知道新的一天就会有新的困...
    白琉璃鹿阅读 117评论 0 0