Список контактов устройства

June 10, 2020

Задача: взять контакты пользователя из устройства и вывести их в виде таблицы. Оказалось, это довольно просто, достаточно вставить одну встроенную в Foundation библиотеку и написать один метод.

Сначала импортируем библиотеку:

import UIKit

import Contacts

После чего создаём модель для контакта. Имя, фамилия и номер телефона - этого достаточно:

 

struct FetchedContact {

    let givenName: String

    let familyName: String

    let phoneNumber: String

}

В ViewController создаём массив:

private var contacts: [FetchedContact] = []

    

Добавим метод fetchContacts(для запроса контактов. Сначала он просит доступ к контактам, после чего, если доступ дан (if granted {) он делает запрос к списку контактов (я оставил ключевые слова для имён, фамилий и телефонов, хотя последний не использовал), затем добавляет их в массив, и там же этот массив сортирует по алфавиту. После этого в главном треде происходит обновление таблицы (всё это время таблица пустая, и наверное, при большом списке контактов, заполнение массива и его сортировка могут занять некоторое время, в этом случае стоит добавить индикатор активности).

 

func fetchContacts() {

        let store = CNContactStore()

        store.requestAccess(for: .contacts) { (granted, error) in

            if let error = error {

                print("Failed to request access:", error)

                return

            }

            guard granted else {

                print("Access denied")

                return

            }

            let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]

            let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])

            do {

                try store.enumerateContacts(with: request, usingBlock: { (contact, _) in

                    self.contacts.append(FetchedContact(givenName: contact.givenName,

                                                        familyName: contact.familyName,

                                                        phoneNumber: contact.phoneNumbers.first?.value.stringValue ?? ""))

                    self.contacts.sort { $0.givenName < $1.givenName }

                })

            } catch let error {

                print("Failed to enumerate contact:", error)

            }

            DispatchQueue.main.async {

                self.tableView.reloadData()

            }

        }

    }

Не забываем его вызвать:

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

        fetchContacts()

    }

    

Вызов функции - чуть ли не самое важное при её написании

Для работы таблицы добавляем расширение с функциями таблицы:

 

extension ViewController: UITableViewDelegate, UITableViewDataSource {

    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return contacts.count

    }

    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = UITableViewCell()

        cell.textLabel?.text = contacts[indexPath.row].givenName

        return cell

    }

    

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        tableView.deselectRow(at: indexPath, animated: true)

        print(contacts[indexPath.row])

    }

    

}

При нажатии на ячейку в консоль выводится имя-фамилия-номер контакта.

Ещё одна вещь, которую нужно сделать: в файле Info.plist добавляем строчку 

Key Type Value
Privacy - Contacts Usage Description String Please grant access to your contacts to invite friends

Готово!