版本记录
版本号 | 时间 |
---|---|
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
框架的一个简单示例,感兴趣的给个赞或者关注~~~