在以前iOS開發中,涉及聯系人相關的編程,代碼都非常繁瑣,並且框架的設計也不是Objective-C風格的,這使開發者用起來非常的難受。在iOS9中,apple終於解決了這個問題,全新的Contacts Framework將完全替代AddressBookFramework,AddressBookFramework也將成為歷史被棄用。至於AddressBookFramework的相關api如何繁瑣,在以前的博客中有記錄,地址如下:
聯系人信息相關編程:http://my.oschina.net/u/2340880/blog/407347。
聯系人UI界面相關編程:http://my.oschina.net/u/2340880/blog/407973。
這一新的框架是iOS9新特性中十分受歡迎的一個。apple的Objective—C體系也更加完善與強大。
新的框架的整體思路是通過配置與請求來管理聯系人,這樣做有一個非常大的好處,邏輯簡單,代碼層次清晰。如下,通過添加一個聯系人來向大家做演示:
這個對象是用來配置聯系人信息的,有可變的CNMutaleContact和CNContact,區別用來讀取和創建聯系人。CNContact對象中有許多屬性,對應聯系人的一些信息。
首先,創建CNMutableContact對象:
? 1
CNMutableContact*contact=[[CNMutableContactalloc]init];
設置聯系人頭像:
? 1contact.imageData=UIImagePNGRepresentation([UIImageimageNamed:@
"Icon-114.png"
]);
設置聯系人姓名:
? 1 2 3 4
//設置名字
contact.givenName=@
"jaki"
;
//設置姓氏
contact.familyName=@
"zhang"
;
設置聯系人郵箱:
? 1 2 3
CNLabeledValue*homeEmail=[CNLabeledValuelabeledValueWithLabel:CNLabelHomevalue:@
"[email protected]"
];
CNLabeledValue*workEmail=[CNLabeledValuelabeledValueWithLabel:CNLabelWorkvalue:@
"[email protected]"
];
contact.emailAddresses=@[homeEmail,workEmail];
這裡需要注意,emailAddresses屬性是一個數組,數組中是才CNLabeledValue對象,CNLabeledValue對象主要用於創建一些聯系人屬性的鍵值對應,通過這些對應,系統會幫我們進行數據的格式化,例如CNLabelHome,就會將號碼格式成家庭郵箱的格式,相應的其他鍵如下:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15//家庭
CONTACTS_EXTERNNSString*
const
CNLabelHomeNS_AVAILABLE(10_11,9_0);
//工作
CONTACTS_EXTERNNSString*
const
CNLabelWorkNS_AVAILABLE(10_11,9_0);
//其他
CONTACTS_EXTERNNSString*
const
CNLabelOtherNS_AVAILABLE(10_11,9_0);
//郵箱地址
CONTACTS_EXTERNNSString*
const
CNLabelEmailiCloudNS_AVAILABLE(10_11,9_0);
//url地址
CONTACTS_EXTERNNSString*
const
CNLabelURLAddressHomePageNS_AVAILABLE(10_11,9_0);
//日期
CONTACTS_EXTERNNSString*
const
CNLabelDateAnniversaryNS_AVAILABLE(10_11,9_0);
設置聯系人電話:
? 1contact.phoneNumbers=@[[CNLabeledValuelabeledValueWithLabel:CNLabelPhoneNumberiPhonevalue:[CNPhoneNumberphoneNumberWithStringValue:@
"12344312321"
]]];
聯系人電話的配置方式和郵箱類似,鍵值如下:
? 1 2 3 4 5 6 7CONTACTS_EXTERNNSString*
const
CNLabelPhoneNumberiPhoneNS_AVAILABLE(10_11,9_0);
CONTACTS_EXTERNNSString*
const
CNLabelPhoneNumberMobileNS_AVAILABLE(10_11,9_0);
CONTACTS_EXTERNNSString*
const
CNLabelPhoneNumberMainNS_AVAILABLE(10_11,9_0);
CONTACTS_EXTERNNSString*
const
CNLabelPhoneNumberHomeFaxNS_AVAILABLE(10_11,9_0);
CONTACTS_EXTERNNSString*
const
CNLabelPhoneNumberWorkFaxNS_AVAILABLE(10_11,9_0);
CONTACTS_EXTERNNSString*
const
CNLabelPhoneNumberOtherFaxNS_AVAILABLE(10_11,9_0);
CONTACTS_EXTERNNSString*
const
CNLabelPhoneNumberPagerNS_AVAILABLE(10_11,9_0);
這裡的CNPhoneNumber對象也是iOS9中的一個新的類,專門用來創建電話號碼,之中方法如下:
? 1 2 3 4 5 6 7 8 9 10@interfaceCNPhoneNumber:NSObject<NSCopying,NSSecureCoding>
//通過類方法創建
+(instancetype)phoneNumberWithStringValue:(NSString*)stringValue;
//通過初始化方法創建
-(instancetype)initWithStringValue:(NSString*)string;
@property(readonly,copy,NS_NONATOMIC_IOSONLY)NSString*stringValue;
@end
設置聯系人地址:
? 1 2 3 4 5 6
CNMutablePostalAddress*homeAdress=[[CNMutablePostalAddressalloc]init];
homeAdress.street=@
"貝克街"
;
homeAdress.city=@
"倫敦"
;
homeAdress.state=@
"英國"
;
homeAdress.postalCode=@
"221B"
;
contact.postalAddresses=@[[CNLabeledValuelabeledValueWithLabel:CNLabelHomevalue:homeAdress]];
設置生日:
? 1 2 3 4 5NSDateComponents*birthday=[[NSDateComponentsalloc]init];
birthday.day=7;
birthday.month=5;
birthday.year=1992;
contact.birthday=birthday;
CNSaveRequest是用於存儲聯系人的請求類,通過這個類,我們可以創建批量添加、修改或者刪除聯系人的請求,例如添加上面我們創建的聯系人對象:
? 1 2 3 4
//初始化方法
CNSaveRequest*saveRequest=[[CNSaveRequestalloc]init];
//添加聯系人
[saveRequestaddContact:contacttoContainerWithIdentifier:nil];
這個類中還有許多方便我們操作的方法:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24@interfaceCNSaveRequest:NSObject
//添加一個聯系人
-(
void
)addContact:(CNMutableContact*)contacttoContainerWithIdentifier:(nullableNSString*)identifier;
//更新一個聯系人
-(
void
)updateContact:(CNMutableContact*)contact;
//刪除一個聯系人
-(
void
)deleteContact:(CNMutableContact*)contact;
//添加一組聯系人
-(
void
)addGroup:(CNMutableGroup*)grouptoContainerWithIdentifier:(nullableNSString*)identifier;
//更新一組聯系人
-(
void
)updateGroup:(CNMutableGroup*)group;
//刪除一組聯系人
-(
void
)deleteGroup:(CNMutableGroup*)group;
//向組中添加子組
-(
void
)addSubgroup:(CNGroup*)subgrouptoGroup:(CNGroup*)groupNS_AVAILABLE(10_11,NA);
//在組中刪除子組
-(
void
)removeSubgroup:(CNGroup*)subgroupfromGroup:(CNGroup*)groupNS_AVAILABLE(10_11,NA);
//向組中添加成員
-(
void
)addMember:(CNContact*)contacttoGroup:(CNGroup*)group;
//向組中移除成員
-(
void
)removeMember:(CNContact*)contactfromGroup:(CNGroup*)group;
@end
CNContactStore是一個用於存取聯系人的上下文橋梁,現在,把我們創建的添加聯系人的請求寫入:
? 1 2
CNContactStore*store=[[CNContactStorealloc]init];
[storeexecuteSaveRequest:saveRequesterror:nil];
在模擬器上運行程序,打開聯系人,效果如下:
聯系人界面:
聯系人詳情:
iOS9中,ContactFramework也為開發者提供了非常方便的格式化信息的方法,還拿我們上面創建的聯系人對象舉例:
NSString*foematter=[CNContactFormatterstringFromContact:contactstyle:CNContactFormatterStyleFullName];
NSLog(@
"%@"
,foematter);
這個運行後會打印出jaki zhang,其中style風格枚舉如下:
? 1 2 3 4 5 6 7typedef
NS_ENUM(NSInteger,CNContactFormatterStyle)
{
//獲取全名
CNContactFormatterStyleFullName,
//獲取拼音全名
CNContactFormatterStylePhoneticFullName,
}NS_ENUM_AVAILABLE(10_11,9_0);
NSString*foematter=[CNPostalAddressFormatterstringFromPostalAddress:homeAdressstyle:CNPostalAddressFormatterStyleMailingAddress];
NSLog(@
"%@"
,foematter);
打印如下:
在開發中,提取聯系人的使用率要遠遠高於創建聯系人,ContactFramework提取聯系人的方式,類似於數據庫的檢索方式,通過配置條件,提取出我們需要的數據,例如:
? 1 2 3 4 5
CNContactStore*stroe=[[CNContactStorealloc]init];
//檢索條件,檢索所有名字中有zhang的聯系人
NSPredicate*predicate=[CNContactpredicateForContactsMatchingName:@
"zhang"
];
//提取數據
NSArray*contacts=[stroeunifiedContactsMatchingPredicate:predicatekeysToFetch:@[CNContactGivenNameKey]error:nil];
keysToFetch是設置提取聯系人的哪些數據,如上則只提取出檢索聯系人的名字。
同樣,也可以通過請求的方式來對聯系人進行遍歷:
? 1 2 3 4 5
CNContactStore*stroe=[[CNContactStorealloc]init];
CNContactFetchRequest*request=[[CNContactFetchRequestalloc]initWithKeysToFetch:@[CNContactPhoneticFamilyNameKey]];
[stroeenumerateContactsWithFetchRequest:requesterror:nilusingBlock:^(CNContact*_Nonnullcontact,
BOOL
*_Nonnullstop){
NSLog(@
"%@"
,contact);
}];
iOS9中,系統也為我們封裝好了一套聯系人的UI界面,用起來也十分方便,主要新增的controller有兩個:
CNContactPickerViewController:展示聯系人列表的controller
CNContactViewController:展示聯系人詳細信息的controller
示例如下:
彈出聯系人列表:
? 1 2
CNContactPickerViewController*con=[[CNContactPickerViewControlleralloc]init];
[selfpresentViewController:conanimated:YEScompletion:nil];
效果如下:
聯系人邏輯的相關處理主要在CNContactPickerDelegate中完成:
? 1 2 3 4 5 6 7//視圖取消時調用的方法
-(
void
)contactPickerDidCancel:(CNContactPickerViewController*)picker;
//選中與取消選中時調用的方法
-(
void
)contactPicker:(CNContactPickerViewController*)pickerdidSelectContact:(CNContact*)contact;
-(
void
)contactPicker:(CNContactPickerViewController*)pickerdidSelectContactProperty:(CNContactProperty*)contactProperty;
-(
void
)contactPicker:(CNContactPickerViewController*)pickerdidSelectContacts:(NSArray<CNContact*>*)contacts;
-(
void
)contactPicker:(CNContactPickerViewController*)pickerdidSelectContactProperties:(NSArray<CNContactProperty*>*)contactProperties;
CNContactViewController則是用來顯示具體聯系人的詳細信息的,比如:
? 1 2
CNContactViewController*con=[CNContactViewControllerviewControllerForContact:contact];
[selfpresentViewController:conanimated:YEScompletion:nil];
相關代理回調函數如下:
? 1 2 3//將要展示聯系人信息與已經展示聯系人信息的回調
-(
BOOL
)contactViewController:(CNContactViewController*)viewControllershouldPerformDefaultActionForContactProperty:(CNContactProperty*)property;
-(
void
)contactViewController:(CNContactViewController*)viewControllerdidCompleteWithContact:(nullableCNContact*)contact;