Swift iOS 9通讯录访问

本文介绍如何在iOS 9及更高版本中使用Contacts Framework替代AddressBook框架访问用户的通讯录。涵盖权限请求、展示系统联系人选择器、查询联系人及添加联系人的详细步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原创Blog,转载请注明出处
http://blog.youkuaiyun.com/hello_hwc?viewmode=list
我的stackoverflow

profile for Leo on Stack Exchange, a network of free, community-driven Q&A sites


前言:在iOS 9之前,一直使用AddressBook这个framework来访问用户通讯录。但是在iOS 9中,AddressBook被废弃了,转而使用Contacts Framework。


文档


Demo效果

下载链接


请求访问权限

相关类
CNContactStore(线程安全)

CNContactStore代表了实际设备上存储,通过这个类可以
- 检查当前的通讯录访问权限
- 请求访问通讯录权限
- fetch通讯录内容(支持按条件fetch,和core data 类似)
- 保存到通讯录

CNContact(线程安全)

表示通讯录中一位联系人的Model类,和NSDictionary类似,他有一个子类是可变的CNMutableContact

示例代码
保存一个store对象,Demo中采用单例
注意,Swift中单例这么写是线程安全的

class ContactsStore{
   static let sharedStore = CNContactStore()
}

请求权限

        let authStatus = CNContactStore.authorizationStatusForEntityType(CNEntityType.Contacts)
          let authStatus = ContactsStore.sharedStore.authorizationStatusForEntityType(CNEntityType.Contacts)
        if authStatus == CNAuthorizationStatus.Denied || authStatus == CNAuthorizationStatus.NotDetermined{
            self.contactsStore.requestAccessForEntityType(CNEntityType.Contacts,
                completionHandler: { (result, error) -> Void in
                    if result == false{
                        let alert = UIAlertController(title: "警告", message: "请在设置中允许通讯录访问,否则App无法正常使用", preferredStyle: UIAlertControllerStyle.Alert)
                        alert.addAction(UIAlertAction(title: "确定", style: UIAlertActionStyle.Cancel , handler: nil))
                        self.presentViewController(alert, animated: true, completion: nil)
                    }
            })
        }

调用系统的ContactsPickerViewController

  1. 让ViewController实现CNContactPickerDelegate协议
    实现如下方法,处理选中的结果
    func contactPicker(picker: CNContactPickerViewController, didSelectContact contact: CNContact) {
        if let phoneNumber =  contact.phoneNumbers.first?.value as? CNPhoneNumber{
            self.textfield.text = phoneNumber.stringValue
        }
    }

然后,模态展示

   let contactsVC = CNContactPickerViewController()
        contactsVC.delegate = self;
        presentViewController(contactsVC, animated:true, completion: nil)

查询全部通讯录

注意,要先指明需要fetch的属性,

因为enumerateContactsWithFetchRequest这个函数会抛出异常,所以要用do-try-catch包括起来

     let keys = [CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactThumbnailImageDataKey]
        let fetchAllRequest = CNContactFetchRequest(keysToFetch:keys)
        do{
            try ContactsStore.sharedStore.enumerateContactsWithFetchRequest(fetchAllRequest) { (contact, pointer) -> Void in
                self.contacts.append(contact)
            }
        }catch{

        }

条件查询

条件查询在示例工程中未列出,按照如下步骤查询
使用如下CNContact方法创建NSPredicate对象

+ predicateForContactsMatchingName:
+ predicateForContactsWithIdentifiers:
...

使用CNContactStore的
- unifiedContactsMatchingPredicate:keysToFetch:error:
来查询


添加

摘自Swift2.1文档

import Contacts

// Creating a mutable object to add to the contact
let contact = CNMutableContact()

contact.imageData = NSData() // The profile picture as a NSData object

contact.givenName = "John"
contact.familyName = "Appleseed"

let homeEmail = CNLabeledValue(label:CNLabelHome, value:"john@example.com")
let workEmail = CNLabeledValue(label:CNLabelWork, value:"j.appleseed@icloud.com")
contact.emailAddresses = [homeEmail, workEmail]

contact.phoneNumbers = [CNLabeledValue(
    label:CNLabelPhoneNumberiPhone,
    value:CNPhoneNumber(stringValue:"(408) 555-0126"))]

let homeAddress = CNMutablePostalAddress()
homeAddress.street = "1 Infinite Loop"
homeAddress.city = "Cupertino"
homeAddress.state = "CA"
homeAddress.postalCode = "95014"
contact.postalAddresses = [CNLabeledValue(label:CNLabelHome, value:homeAddress)]

let birthday = NSDateComponents()
birthday.day = 1
birthday.month = 4
birthday.year = 1988  // You can omit the year value for a yearless birthday
contact.birthday = birthday

// Saving the newly created contact
let store = CNContactStore()
let saveRequest = CNSaveRequest()
saveRequest.addContact(contact, toContainerWithIdentifier:nil)
try store.executeSaveRequest(saveRequest)

本地化/格式化

几个常用的类

  • CNContactFormatter
  • CNPostalAddressFormatter
  • CNContact.localizedStringForKey
  • CNLabeledValue.localizedStringForLabel

举例

从Contact中拼接出全名

let fullName = CNContactFormatter.stringFromContact(contact, style: .FullName)
print(fullName)
// John Appleseed

邮政地址

let postalString = CNPostalAddressFormatter.stringFromPostalAddress(homeAddress)
print(postalString)
// 1 Infinite Loop
// Cupertino
// CA
// 95014

对通讯录的内置Key获取

let displayName = CNContact.localizedStringForKey(CNContactNicknameKey)
print(displayName)
// 昵称,在中文条件下

最后

欢迎关注我的优快云博客,在我每个月都会更新10篇左右的iOS 文章,源码都是Swift的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值