iOS9全新的聯繫人相關框架——Contacts Framework 一、引言 在以前iOS開發中,涉及聯繫人相關的編程,代碼都非常繁瑣,並且框架的設計也不是Objective-C風格的,這使開發者用起來非常的難受。在iOS9中,apple終於解決了這個問題,全新的Contacts Framewor ...
iOS9全新的聯繫人相關框架——Contacts Framework
一、引言
在以前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體系也更加完善與強大。
二、讓我們來添加一個聯繫人
新的框架的整體思路是通過配置與請求來管理聯繫人,這樣做有一個非常大的好處,邏輯簡單,代碼層次清晰。如下,通過添加一個聯繫人來向大家做演示:
1、聯繫人對象:CNContact
這個對象是用來配置聯繫人信息的,有可變的CNMutaleContact和CNContact,區別用來讀取和創建聯繫人。CNContact對象中有許多屬性,對應聯繫人的一些信息。
首先,創建CNMutableContact對象:
?1 |
CNMutableContact * contact = [[CNMutableContact alloc]init];
|
設置聯繫人頭像:
?1 |
contact.imageData = UIImagePNGRepresentation([UIImage imageNamed:@ "Icon-114.png" ]);
|
設置聯繫人姓名:
?1 2 3 4 |
//設置名字
contact.givenName = @ "jaki" ;
//設置姓氏
contact.familyName = @ "zhang" ;
|
設置聯繫人郵箱:
?1 2 3 |
CNLabeledValue *homeEmail = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:@ "[email protected]" ];
CNLabeledValue *workEmail =[CNLabeledValue labeledValueWithLabel:CNLabelWork value:@ "[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_EXTERN NSString * const CNLabelHome NS_AVAILABLE(10_11, 9_0);
//工作
CONTACTS_EXTERN NSString * const CNLabelWork NS_AVAILABLE(10_11, 9_0);
//其他
CONTACTS_EXTERN NSString * const CNLabelOther NS_AVAILABLE(10_11, 9_0);
// 郵箱地址
CONTACTS_EXTERN NSString * const CNLabelEmailiCloud NS_AVAILABLE(10_11, 9_0);
// url地址
CONTACTS_EXTERN NSString * const CNLabelURLAddressHomePage NS_AVAILABLE(10_11, 9_0);
// 日期
CONTACTS_EXTERN NSString * const CNLabelDateAnniversary NS_AVAILABLE(10_11, 9_0);
|
設置聯繫人電話:
?1 |
contact.phoneNumbers = @[[CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberiPhone value:[CNPhoneNumber phoneNumberWithStringValue:@ "12344312321" ]]];
|
聯繫人電話的配置方式和郵箱類似,鍵值如下:
?1 2 3 4 5 6 7 |
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberiPhone NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberMobile NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberMain NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberHomeFax NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberWorkFax NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberOtherFax NS_AVAILABLE(10_11, 9_0);
CONTACTS_EXTERN NSString * const CNLabelPhoneNumberPager NS_AVAILABLE(10_11, 9_0);
|
這裡的CNPhoneNumber對象也是iOS9中的一個新的類,專門用來創建電話號碼,之中方法如下:
?1 2 3 4 5 6 7 8 9 10 |
@interface CNPhoneNumber : 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 = [[CNMutablePostalAddress alloc]init];
homeAdress.street = @ "貝克街" ;
homeAdress.city = @ "倫敦" ;
homeAdress.state = @ "英國" ;
homeAdress.postalCode = @ "221B" ;
contact.postalAddresses = @[[CNLabeledValue labeledValueWithLabel:CNLabelHome value:homeAdress]];
|
設置生日:
?1 2 3 4 5 |
NSDateComponents * birthday = [[NSDateComponents alloc]init];
birthday.day=7;
birthday.month=5;
birthday.year=1992;
contact.birthday=birthday;
|
2、創建添加聯繫人請求:CNSaveRequest
CNSaveRequest是用於存儲聯繫人的請求類,通過這個類,我們可以創建批量添加、修改或者刪除聯繫人的請求,例如添加上面我們創建的聯繫人對象:
?1 2 3 4 |
//初始化方法
CNSaveRequest * saveRequest = [[CNSaveRequest alloc]init];
//添加聯繫人
[saveRequest addContact:contact toContainerWithIdentifier: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 |
@interface CNSaveRequest : NSObject
//添加一個聯繫人
- ( void )addContact:(CNMutableContact *)contact toContainerWithIdentifier:(nullable NSString *)identifier;
//更新一個聯繫人
- ( void )updateContact:(CNMutableContact *)contact;
//刪除一個聯繫人
- ( void )deleteContact:(CNMutableContact *)contact;
//添加一組聯繫人
- ( void )addGroup:(CNMutableGroup *)group toContainerWithIdentifier:(nullable NSString *)identifier;
//更新一組聯繫人
- ( void )updateGroup:(CNMutableGroup *)group;
//刪除一組聯繫人
- ( void )deleteGroup:(CNMutableGroup *)group;
//向組中添加子組
- ( void )addSubgroup:(CNGroup *)subgroup toGroup:(CNGroup *)group NS_AVAILABLE(10_11, NA);
//在組中刪除子組
- ( void )removeSubgroup:(CNGroup *)subgroup fromGroup:(CNGroup *)group NS_AVAILABLE(10_11, NA);
//向組中添加成員
- ( void )addMember:(CNContact *)contact toGroup:(CNGroup *)group;
//向組中移除成員
- ( void )removeMember:(CNContact *)contact fromGroup:(CNGroup *)group;
@end
|
3、進行聯繫人的寫入操作:CNContactStore
CNContactStore是一個用於存取聯繫人的上下文橋梁,現在,把我們創建的添加聯繫人的請求寫入:
?1 2 |
CNContactStore * store = [[CNContactStore alloc]init];
[store executeSaveRequest:saveRequest error:nil];
|
在模擬器上運行程式,打開聯繫人,效果如下:
聯繫人界面:
聯繫人詳情:
三、獲取格式化的聯繫人信息
iOS9中,ContactFramework也為開發者提供了非常方便的格式化信息的方法,還拿我們上面創建的聯繫人對象舉例:
1、獲取格式化的聯繫人姓名
?1 2 |
NSString * foematter =[CNContactFormatter stringFromContact:contact style:CNContactFormatterStyleFullName];
NSLog(@ "%@" ,foematter);
|
這個運行後會列印出jaki zhang,其中style風格枚舉如下:
?1 2 3 4 5 6 7 |
typedef NS_ENUM(NSInteger, CNContactFormatterStyle)
{
//獲取全名
CNContactFormatterStyleFullName,
//獲取拼音全名
CNContactFormatterStylePhoneticFullName,
} NS_ENUM_AVAILABLE(10_11, 9_0);
|
2、獲取格式化的聯繫人地址
?1 2 |
NSString * foematter =[CNPostalAddressFormatter stringFromPostalAddress:homeAdress style:CNPostalAddressFormatterStyleMailingAddress];
NSLog(@ "%@" ,foematter);
|
列印如下:
四、提取聯繫人
在開發中,提取聯繫人的使用率要遠遠高於創建聯繫人,ContactFramework提取聯繫人的方式,類似於資料庫的檢索方式,通過配置條件,提取出我們需要的數據,例如:
?1 2 3 4 5 |
CNContactStore * stroe = [[CNContactStore alloc]init];
//檢索條件,檢索所有名字中有zhang的聯繫人
NSPredicate * predicate = [CNContact predicateForContactsMatchingName:@ "zhang" ];
//提取數據
NSArray * contacts = [stroe unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
|
keysToFetch是設置提取聯繫人的哪些數據,如上則只提取出檢索聯繫人的名字。
同樣,也可以通過請求的方式來對聯繫人進行遍歷:
?1 2 3 4 5 |
CNContactStore * stroe = [[CNContactStore alloc]init];
CNContactFetchRequest * request = [[CNContactFetchRequest alloc]initWithKeysToFetch:@[CNContactPhoneticFamilyNameKey]];
[stroe enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
NSLog(@ "%@" ,contact);
}];
|
五、ContactFramework UI相關
iOS9中,系統也為我們封裝好了一套聯繫人的UI界面,用起來也十分方便,主要新增的controller有兩個:
CNContactPickerViewController:展示聯繫人列表的controller
CNContactViewController:展示聯繫人詳細信息的controller
示例如下:
彈出聯繫人列表:
?1 2 |
CNContactPickerViewController * con = [[CNContactPickerViewController alloc]init];
[self presentViewController:con animated:YES completion:nil];
|
效果如下:
聯繫人邏輯的相關處理主要在CNContactPickerDelegate中完成:
?1 2 3 4 5 6 7 |
//視圖取消時 調用的方法
- ( 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;
- ( void )contactPicker:(CNContactPickerViewController *)picker didSelectContactProperties:(NSArray<CNContactProperty*> *)contactProperties;
|
CNContactViewController則是用來顯示具體聯繫人的詳細信息的,比如:
?1 2 |
CNContactViewController * con = [CNContactViewController viewControllerForContact:contact];
[self presentViewController:con animated:YES completion:nil];
|
相關代理回調函數如下:
?1 2 3 |
//將要展示聯繫人信息與已經展示聯繫人信息的回調
- ( BOOL )contactViewController:(CNContactViewController *)viewController shouldPerformDefaultActionForContactProperty:(CNContactProperty *)property;
- ( void )contactViewController:(CNContactViewController *)viewController didCompleteWithContact:(nullable CNContact *)contact;
|