版本记录
| 版本号 | 时间 |
|---|---|
| V1.0 | 2019.06.18 星期二 |
前言
有关通讯录的框架有好几种,包括
AddressBook、AddressBookUI、Contacts和ContactsUI,这里,iOS9以后AddressBook、AddressBookUI就不推荐使用了,但是如果要支持ios8以及以前的系统还是要用它们两个框架的。ios9以后系统推荐使用Contacts和ContactsUI,接下来的几篇我们就详细的解析一下这几个框架。感兴趣的可以看我写的上面几篇。
1. 通讯录相关框架详细解析(一)—— AddressBook框架基本概览
2. 通讯录相关框架详细解析(二)—— AddressBookUI框架基本概览
3. 通讯录相关框架详细解析(三)—— Contacts框架基本概览(一)
4. 通讯录相关框架详细解析(四)—— ContactsUI框架基本概览(一)
5. 通讯录相关框架详细解析(五)—— Contacts和ContactsUI框架的基本使用示例(一)
源码
1. Swift
首先看下代码组织结构

下面就是sb中的内容

接着就是源码了
1. AppDelegate.swift
import UIKit
import Contacts
extension UIColor {
static let appBlue = UIColor(red: 0, green: 155.0 / 255.0, blue: 255.0 / 255.0, alpha: 1)
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window?.backgroundColor = .white
UINavigationBar.appearance().barStyle = .default
UINavigationBar.appearance().barTintColor = .appBlue
UINavigationBar.appearance().tintColor = .white
UINavigationBar.appearance().isOpaque = true
UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: UIColor.white]
UITabBar.appearance().tintColor = .appBlue
CNContactStore().requestAccess(for: .contacts) { (access, error) in
print("Access: \(access)")
}
return true
}
}
2. FriendsViewController.swift
import UIKit
import ContactsUI
class FriendsViewController: UITableViewController {
var friendsList = Friend.defaultContacts()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.titleView = UIImageView(image: UIImage(named: "RWConnectTitle")!)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.tintColor = .white
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if
segue.identifier == "EditFriendSegue",
// 1
let cell = sender as? FriendCell,
let indexPath = tableView.indexPath(for: cell),
let editViewController = segue.destination as? EditFriendTableViewController {
let friend = friendsList[indexPath.row]
// 2
let store = CNContactStore()
// 3
let predicate = CNContact.predicateForContacts(matchingEmailAddress: friend.workEmail)
// 4
let keys = [CNContactPhoneNumbersKey as CNKeyDescriptor]
// 5
if
let contacts = try? store.unifiedContacts(matching: predicate, keysToFetch: keys),
let contact = contacts.first,
let contactPhone = contact.phoneNumbers.first {
// 6
friend.storedContact = contact.mutableCopy() as? CNMutableContact
friend.phoneNumberField = contactPhone
friend.identifier = contact.identifier
}
editViewController.friend = friend
}
}
@IBAction private func addFriends(sender: UIBarButtonItem) {
// 1
let contactPicker = CNContactPickerViewController()
contactPicker.delegate = self
// 2
contactPicker.predicateForEnablingContact = NSPredicate(format: "emailAddresses.@count > 0")
present(contactPicker, animated: true)
}
}
//MARK: - UITableViewDataSource
extension FriendsViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return friendsList.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FriendCell", for: indexPath)
if let cell = cell as? FriendCell {
let friend = friendsList[indexPath.row]
cell.friend = friend
}
return cell
}
}
//MARK: - UITableViewDelegate
extension FriendsViewController {
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
// 1
let friend = friendsList[indexPath.row]
let contact = friend.contactValue
// 2
let contactViewController = CNContactViewController(forUnknownContact: contact)
contactViewController.hidesBottomBarWhenPushed = true
contactViewController.allowsEditing = false
contactViewController.allowsActions = false
// 3
navigationController?.navigationBar.tintColor = .appBlue
navigationController?.pushViewController(contactViewController, animated: true)
}
}
//MARK: - CNContactPickerDelegate
extension FriendsViewController: CNContactPickerDelegate {
func contactPicker(_ picker: CNContactPickerViewController,
didSelect contacts: [CNContact]) {
let newFriends = contacts.compactMap { Friend(contact: $0) }
for friend in newFriends {
if !friendsList.contains(friend) {
friendsList.append(friend)
}
}
tableView.reloadData()
}
}
3. EditFriendTableViewController.swift
import UIKit
import Contacts
class EditFriendTableViewController: UITableViewController {
@IBOutlet private weak var nameLabel: UILabel!
@IBOutlet private weak var emailLabel: UILabel!
@IBOutlet private weak var phoneTypeLabel: UILabel!
@IBOutlet private weak var phoneTextField: UITextField!
@IBOutlet private weak var saveButton: UIButton!
var friend: Friend?
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
private func setup() {
guard let friend = friend else {
nameLabel.text = ""
emailLabel.text = ""
phoneTextField.text = ""
phoneTextField.isEnabled = false
return
}
let formatter = CNContactFormatter()
formatter.style = .fullName
if let name = formatter.string(from: friend.contactValue) {
nameLabel.text = name
} else {
nameLabel.text = "Name Not Available"
}
emailLabel.text = friend.workEmail
if let phoneNumberField = friend.phoneNumberField,
let label = phoneNumberField.label {
phoneTypeLabel.text = CNLabeledValue<CNPhoneNumber>.localizedString(forLabel: label)
phoneTextField.text = phoneNumberField.value.stringValue
}
}
@IBAction private func save(_ sender: Any) {
phoneTextField.resignFirstResponder()
let store = CNContactStore()
guard let friend = friend,
let phoneNumberText = phoneTextField.text else { return }
let phoneNumberValue = CNPhoneNumber(stringValue: phoneNumberText)
let saveRequest = CNSaveRequest()
if let storedContact = friend.storedContact,
let phoneNumberToEdit = storedContact.phoneNumbers.first(
where: { $0 == friend.phoneNumberField }
),
let index = storedContact.phoneNumbers.firstIndex(of: phoneNumberToEdit) {
// 1
let newPhoneNumberField = phoneNumberToEdit.settingValue(phoneNumberValue)
storedContact.phoneNumbers.remove(at: index)
storedContact.phoneNumbers.insert(newPhoneNumberField, at: index)
friend.phoneNumberField = newPhoneNumberField
// 2
saveRequest.update(storedContact)
friend.storedContact = nil
} else if let unsavedContact = friend.contactValue.mutableCopy() as? CNMutableContact {
// 3
let phoneNumberField = CNLabeledValue(label: CNLabelPhoneNumberMain,
value: phoneNumberValue)
unsavedContact.phoneNumbers = [phoneNumberField]
friend.phoneNumberField = phoneNumberField
// 4
saveRequest.add(unsavedContact, toContainerWithIdentifier: nil)
}
do {
try store.execute(saveRequest)
let controller = UIAlertController(title: "Success",
message: nil,
preferredStyle: .alert)
controller.addAction(UIAlertAction(title: "OK", style: .default))
present(controller, animated: true)
setup()
} catch {
print(error)
}
}
}
4. Friend.swift
import UIKit
import Contacts
class Friend {
let firstName: String
let lastName: String
let workEmail: String
var identifier: String?
let profilePicture: UIImage?
var storedContact: CNMutableContact?
var phoneNumberField: (CNLabeledValue<CNPhoneNumber>)?
init(firstName: String, lastName: String, workEmail: String, profilePicture: UIImage?){
self.firstName = firstName
self.lastName = lastName
self.workEmail = workEmail
self.profilePicture = profilePicture
}
static func defaultContacts() -> [Friend] {
return [
Friend(firstName: "Mic", lastName: "Pringle", workEmail: "mic@example.com", profilePicture: UIImage(named: "MicProfilePicture")),
Friend(firstName: "Ray", lastName: "Wenderlich", workEmail: "ray@example.com", profilePicture: UIImage(named: "RayProfilePicture")),
Friend(firstName: "Sam", lastName: "Davies", workEmail: "sam@example.com", profilePicture: UIImage(named: "SamProfilePicture")),
Friend(firstName: "Greg", lastName: "Heo", workEmail: "greg@example.com", profilePicture: UIImage(named: "GregProfilePicture"))]
}
}
extension Friend: Equatable {
static func ==(lhs: Friend, rhs: Friend) -> Bool{
return lhs.firstName == rhs.firstName &&
lhs.lastName == rhs.lastName &&
lhs.workEmail == rhs.workEmail &&
lhs.profilePicture == rhs.profilePicture
}
}
extension Friend {
var contactValue: CNContact {
let contact = CNMutableContact()
contact.givenName = firstName
contact.familyName = lastName
contact.emailAddresses = [CNLabeledValue(label: CNLabelWork, value: workEmail as NSString)]
if let profilePicture = profilePicture {
let imageData = profilePicture.jpegData(compressionQuality: 1)
contact.imageData = imageData
}
if let phoneNumberField = phoneNumberField {
contact.phoneNumbers.append(phoneNumberField)
}
return contact.copy() as! CNContact
}
convenience init?(contact: CNContact) {
guard let email = contact.emailAddresses.first else { return nil }
let firstName = contact.givenName
let lastName = contact.familyName
let workEmail = email.value as String
var profilePicture: UIImage?
if let imageData = contact.imageData {
profilePicture = UIImage(data: imageData)
}
self.init(firstName: firstName, lastName: lastName, workEmail: workEmail, profilePicture: profilePicture)
if let contactPhone = contact.phoneNumbers.first {
phoneNumberField = contactPhone
}
}
}
5. FriendCell.swift
import UIKit
import Contacts
class FriendCell: UITableViewCell {
@IBOutlet private weak var contactNameLabel: UILabel!
@IBOutlet private weak var contactEmailLabel: UILabel!
@IBOutlet private weak var contactImageView: UIImageView! {
didSet {
contactImageView.layer.masksToBounds = true
contactImageView.layer.cornerRadius = 22.0
}
}
var friend : Friend? {
didSet {
configureCell()
}
}
private func configureCell() {
let formatter = CNContactFormatter()
formatter.style = .fullName
guard let friend = friend,
let name = formatter.string(from: friend.contactValue) else { return }
contactNameLabel.text = name
contactEmailLabel.text = friend.workEmail
contactImageView.image = friend.profilePicture ?? UIImage(named: "PlaceholderProfilePic")
}
}
后记
本篇主要讲述了
Contacts和ContactsUI框架的一个简单示例,感兴趣的给个赞或者关注~~~
