ManagingContacts/ManagingContacts/SearchViewController.swift
/* |
Copyright (C) 2017 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
A table view controller that allows you to search contacts by |
name (first name, last name, and organization name). |
*/ |
import Contacts |
import UIKit |
class SearchViewController: UITableViewController, UISearchResultsUpdating { |
// MARK: - Types |
fileprivate struct MainStoryboard { |
struct TableViewCellIdentifiers { |
static let cellIdentifier = "cellID" |
static let cellSubtitleIdentifier = "cellSubtitleID" |
} |
} |
// MARK: - Properties |
/// Stores all contacts available in the contact store. |
fileprivate var allContacts = [CNContact]() |
// Stores contacts matching the search string. |
fileprivate var filteredContacts = [CNContact]() |
fileprivate var searchController: UISearchController! |
/** |
- returns: Boolean value that determines whether to show a subtitle cell.\ |
true if the contact is a person and the matching name was found |
in its associated organization name rather than in its name. |
Also true if the contact is an organization and the matching |
name was found in its associated formatted name. false, |
otherwise. |
*/ |
fileprivate var shouldShowSubtitleCell: Bool = false |
var data: [CNContact] = [CNContact]() { |
didSet { |
filteredContacts = data |
allContacts = data |
tableView.reloadData() |
} |
} |
// MARK: - View Life Cycle |
override func viewDidLoad() { |
super.viewDidLoad() |
// Create the search controller. |
searchController = UISearchController(searchResultsController: nil) |
searchController.searchResultsUpdater = self |
// Make sure the that the search bar is visible within the navigation bar. |
searchController.searchBar.sizeToFit() |
// Include the search controller's search bar in the table header view. |
tableView.tableHeaderView = searchController.searchBar |
searchController.dimsBackgroundDuringPresentation = false |
definesPresentationContext = true |
} |
// MARK: - UITableViewDataSource |
override func numberOfSections(in tableView: UITableView) -> Int { |
return 1 |
} |
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
return filteredContacts.count |
} |
// MARK: - UITableViewDelegate |
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
var cell: UITableViewCell |
let contact = filteredContacts[indexPath.row] |
var name = String() |
if let searchString = searchController.searchBar.text, !(searchString.isEmpty) { |
/* CNContact's predicateForContactsMatchingName looks thru the first |
name, last name, and organization name fields of a contact. In |
some cases, Contacts may find the searched name in the organization |
name of a contact, which is a person or in the first name and |
last name of a contact, which is an organization. |
Display a subtitle cell if the contact is a person and its first |
name and last name do not contain the search string. |
*/ |
if contact.isPerson && !(contact.formattedName.localizedCaseInsensitiveContains(searchString)) { |
name = contact.organizationName |
shouldShowSubtitleCell = true |
} |
// Display a subtitle cell if the contact is an organization and its name does not contain the searchString |
else if !contact.isPerson && !(contact.organizationName.localizedCaseInsensitiveContains(searchString)) { |
name = (contact.familyName.localizedCaseInsensitiveContains(searchString)) ? contact.familyName : contact.givenName |
shouldShowSubtitleCell = true |
} |
} |
if shouldShowSubtitleCell { |
cell = tableView.dequeueReusableCell(withIdentifier: MainStoryboard.TableViewCellIdentifiers.cellSubtitleIdentifier, for: indexPath) |
// Display the name of the contact. |
cell.textLabel!.text = (contact.isPerson) ? contact.formattedName : contact.organizationName |
// Display the contact's associated field containing the search string. |
cell.detailTextLabel!.text = name |
} |
else { |
cell = tableView.dequeueReusableCell(withIdentifier: MainStoryboard.TableViewCellIdentifiers.cellIdentifier, for: indexPath) |
cell.textLabel!.text = (contact.isPerson) ? contact.formattedName : contact.organizationName |
} |
return cell |
} |
// MARK: - UISearchResultsUpdating |
func updateSearchResults(for searchController: UISearchController) { |
let searchString = searchController.searchBar.text |
/* |
Show all contacts if the user did not enter anything. Show the |
contacts matching the search string otherwise. |
*/ |
if searchString!.isEmpty { |
filteredContacts = allContacts |
tableView.reloadData() |
} |
else { |
MGCContactStore.sharedInstance.fetchContacts(with: searchString!, completion: ({(contacts: [CNContact]) in |
self.filteredContacts = contacts |
self.tableView.reloadData() |
})) |
} |
} |
// MARK: - Memory Management |
override func didReceiveMemoryWarning() { |
super.didReceiveMemoryWarning() |
} |
} |
Copyright © 2017 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2017-02-11