苹果在iOS9的SDK中废除了AddressBookUI.framework的一些功能(是不是这个库都废除了,有待验证),具体和保存联系人相关的几个系统界面如下:
联系人选择:AddressBookUI/ABPeoplePickerNavigationController.h
联系人详情:AddressBookUI/ABPersonViewController.h
未知联系人:AddressBookUI/ABUnknownPersonViewController.h
新建联系人:AddressBookUI/ABNewPersonViewController.h
新的SDK中使用
联系人选择:ContactsUI/CNContactPickerViewController.h
联系人详情、新建联系人、未知联系人:ContactsUI/CNContactViewController.h(使用不同方法创建,下面会说)
下面的链接是官方的ppt,讲的很详细,不过是swift版本
http://devstreaming.apple.com/videos/wwdc/2015/223rmo6dv9hxh/223/223_introducing_the_contacts_framework_for_ios_and_os_x.pdf
我要分享的是OC的实现,下面是我的实例。
一.需求
我的老项目里面的需求和微信的效果是一样的(下图为微信截图),这里先吐槽下,这个功能实现起来要区分ios7(6),ios8,ios9
二.思路
保存新联系人非常简单使用系统的新建联系人页,把需要保存的对象封装传入,剩下的交给系统处理就好;
保存现有联系人可能就费点心思了,有两种方式一个是使用未知联系人页面处理(我的客户比较NB,必须按需求100%实现),另一种是先跳转到选择页面中获取一个现有联系人的对象,再跳转到新建好友页面(把该对象传入),之后的事情交给系统处理(这个困扰了我很久,后来受到微信的启发,才想出来这个野路子)
三.实现(模拟器无法保存,请用真机调试),demo: Contact4iOS9.zip (38
K) 下载次数:36
导入头文件
#import <ContactsUI/CNContactViewController.h>
#import <ContactsUI/CNContactPickerViewController.h>
保存新联系人实现
- (void)saveNewContact{
//1.创建Contact对象,必须是可变的
CNMutableContact *contact = [[CNMutableContact alloc] init];
//2.为contact赋值,这块比较恶心,很混乱,setValue4Contact中会给出常用值的对应关系
[self setValue4Contact:contact existContect:NO];
//3.创建新建好友页面
CNContactViewController *controller = [CNContactViewController viewControllerForNewContact:contact];
//代理内容根据自己需要实现
controller.delegate = self;
//4.跳转
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:controller];
[self presentViewController:navigation animated:YES completion:^{
}];
}
保存现有联系人实现
//保存现有联系人实现
- (void)saveExistContact{
//1.跳转到联系人选择页面,注意这里没有使用UINavigationController
CNContactPickerViewController *controller = [[CNContactPickerViewController alloc] init];
controller.delegate = self;
[self presentViewController:controller animated:YES completion:^{
}];
}
//2.实现点选的代理,其他代理方法根据自己需求实现
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact{
[picker dismissViewControllerAnimated:YES completion:^{
//3.copy一份可写的Contact对象,不要尝试alloc一类,mutableCopy独此一家
CNMutableContact *c = [contact mutableCopy];
//4.为contact赋值
[self setValue4Contact:c existContect:YES];
//5.跳转到新建联系人页面
CNContactViewController *controller = [CNContactViewController viewControllerForNewContact:c];
controller.delegate = self;
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:controller];
[self presentViewController:navigation animated:YES completion:^{
}];
}];
}
对应关系
//设置要保存的contact对象
- (void)setValue4Contact:(CNMutableContact *)contact existContect:(BOOL)exist{
if (!exist) {
//名字和头像
contact.nickname = @"oriccheng";
// UIImage *logo = [UIImage imageNamed:@"..."];
// NSData *dataRef = UIImagePNGRepresentation(logo);
// contact.imageData = dataRef;
}
//电话,每一个CNLabeledValue都是有讲究的,如何批评,可以在头文件里面查找,这里给出几个常用的,别的我也不愿意去研究
CNLabeledValue *phoneNumber = [CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberMobile value:[CNPhoneNumber
phoneNumberWithStringValue:@"18888888888"]];
if (!exist) {
contact.phoneNumbers = @[phoneNumber];
}
//现有联系人情况
else{
if ([contact.phoneNumbers count] >0) {
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] initWithArray:contact.phoneNumbers];
[phoneNumbers addObject:phoneNumber];
contact.phoneNumbers = phoneNumbers;
}else{
contact.phoneNumbers = @[phoneNumber];
}
}
//网址:CNLabeledValue *url = [CNLabeledValue labeledValueWithLabel:@"" value:@""];
//邮箱:CNLabeledValue *mail = [CNLabeledValue labeledValueWithLabel:CNLabelWork value:self.poiData4Save.mail];
//特别说一个地址,PostalAddress对应的才是地址
CNMutablePostalAddress *address = [[CNMutablePostalAddress alloc] init];
address.state = @"辽宁省";
address.city = @"沈阳市";
address.postalCode = @"111111";
//外国人好像都不强调区的概念,所以和具体地址拼到一起
address.street = @"沈河区惠工街10号";
//生成的上面地址的CNLabeledValue,其中可以设置类型CNLabelWork等等
CNLabeledValue *addressLabel = [CNLabeledValue labeledValueWithLabel:CNLabelWork value:address];
if (!exist) {
contact.postalAddresses = @[addressLabel];
}else{
if ([contact.postalAddresses count] >0) {
NSMutableArray *addresses = [[NSMutableArray alloc] initWithArray:contact.postalAddresses];
[addresses addObject:addressLabel];
contact.postalAddresses = addresses;
}else{
contact.postalAddresses = @[addressLabel];
}
}
}
四.一个未解决bug:
联系人编辑页面点击拍照,无法拍照,黑屏,我看微信也是这样的,还在找出问题的原因
五.总结
新的方法整体比之前更加面向对象了,不像之前这copy那copy的,好用了一些,但是联系人的属性实在太多了,代码写起来很慢,另外苹果也提供了新的联系人读写操作的方法,用起来也同样比之前的更好理解,主要类是CNSaveRequest和CNContactStore,用起来和FMDB很像,这里就不举例了,最后吐槽下苹果吧,现在iOS系统升级给老程序带来了很多的工作,我在做的就是一个三年前的老项目,本身就很庞大复杂,还不断在修改需求、加功能,真是被苹果玩吐血啊。
六.附赠我遇到的iOS9必改内容
1.国际化判断
2.高级的定位功能
3.https加密问题
4.老程序使用Default.png方式设置欢迎页面,无法获取屏幕高度
5.联系人api更换