In the world of iOS app development, the Contacts framework becomes a valuable tool for accessing a user’s contacts. In this tutorial, we embark on a journey to retrieve and showcase all of a user’s contacts within a table view. This tutorial has been crafted with Xcode 11, tailored for iOS 13.

Setting Up the Project

1. Launch Xcode and initiate a fresh Single View App project.

2. Name your project “IOSFetchContactsTutorial”

Then provide your customary Organization Name and Organization Identifier. Select Swift as the programming language and opt for Storyboard as the User Interface. Click Next.

3. Crafting the User Interface

Within the storyboard, clear the canvas of the default View Controller, and introduce a Navigation Controller to the Scene. This action will automatically include a Table View Controller. Select the Navigation Controller, and in the Attribute inspector, mark the “Is Initial View Controller” checkbox.

4. Proceed to select the Table View Cell 

Then navigate to the Attributes Inspector. In the Table View Cell section, modify the Style to Subtitle and set the Identifier to “Cell.”

5. Remove the ViewController.swift file from the project

Since the View Controller is no longer required in the Storyboard, you can safely remove the ViewController.swift file from the project. In its place, include a new file by choosing iOS -> Source -> Cocoa Touch Class. Name this file “TableViewController” and make it a subclass of UITableViewController.

6. Ensure the TableViewController class is linked to the Table View Controller object within the Storyboard. 

Select the object and access the Identity Inspector. Adjust the class to “TableViewController.”

7. Introduce an empty Swift file

To manage contact data efficiently, introduce an empty Swift file named “FetchedContact.swift” and insert the following code:

```swift
import Foundation
import Contacts

struct FetchedContact {
    var firstName: String
    var lastName: String
    var telephone: String
}
```

These properties within the FetchContact struct will play a pivotal role in presenting the contacts within the table view.

8. Head to the TableViewController.swift file 

Then create an empty array to store the table data:

```swift
var contacts = [FetchedContacts]()
```

9. Modify the following delegate methods within the TableViewController class:

```swift
override func numberOfSections(in tableView: UITableView) -> Int {
    return 1 // There's only one section in the Table View.
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return contacts.count // The number of rows equals the count of contacts.
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    cell.textLabel?.text = contacts[indexPath.row].firstName + " " + contacts[indexPath.row].lastName
    cell.detailTextLabel?.text = contacts[indexPath.row].telephone

    return cell
}
```

10. To retrieve the contacts, enhance the viewDidLoad method:

```swift
override func numberOfSections(in tableView: UITableView) -> Int {
    return 1 // There's only one section in the Table View.
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return contacts.count // The number of rows equals the count of contacts.
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    cell.textLabel?.text = contacts[indexPath.row].firstName + " " + contacts[indexPath.row].lastName
    cell.detailTextLabel?.text = contacts[indexPath.row].telephone

    return cell
}
```

11. Introduce the fetchContacts method:

```swift
private func fetchContacts() {
    let store = CNContactStore()
    store.requestAccess(for: .contacts) { (granted, error) in
        if let error = error {
            print("Failed to request access", error)
            return
        }
        if granted {
            let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]
            let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
            do {
                try store.enumerateContacts(with: request, usingBlock: { (contact, stopPointer) in
                    self.contacts.append(FetchedContact(firstName: contact.givenName, lastName: contact.familyName, telephone: contact.phoneNumbers.first?.value.stringValue ?? ""))
                })
            } catch let error {
                print("Failed to enumerate contact", error)
            }
        } else {
            print("Access denied")
        }
    }
}
```

To ensure access to the user’s contacts, don’t forget to update the info.plist file as well.

12. Build and Run your project

After gaining access, witness the names and telephone numbers of the current contacts elegantly displayed within the table view.

In Conclusion 

In the realm of iOS app development, harnessing the power of the Contacts framework proves invaluable for retrieving a user’s contact information. This tutorial embarks on a journey to showcase all of the user’s contacts within a table view, tailored for iOS 13 and built with Xcode 11. To embark on this coding adventure, start by creating a new project in Xcode, aptly named “IOSFetchContactsTutorial.” Configure the project settings with your Organization Name, Organization Identifier, and opt for Swift as the programming language along with Storyboard as the User Interface.

Within the storyboard canvas, initiate a Navigation Controller, which automatically adds a Table View Controller. Don’t forget to set the Navigation Controller as the initial view controller. Customize the appearance of your table view by selecting the Table View Cell and adjusting its style to Subtitle while setting the Identifier to “Cell.” In the code structure, replace the default View Controller with a custom TableViewController. Ensure this new class is linked within the Storyboard. To efficiently manage contact data, introduce a “FetchedContact” Swift struct to represent contact information. This struct includes properties for first name, last name, and telephone number.

Within the TableViewController class, create an empty array named “contacts” to store contact data. Customize the table view behavior by modifying delegate methods, specifying the number of sections and rows, and configuring cell content display. This tutorial empowers you to tap into the Contacts framework, providing a practical foundation for creating contact-based apps in the iOS ecosystem.

Leave a Reply