Converting from a table view to a collection view

Showing a user's contacts in the form of a list is a fine idea. It's functional, looks all right, and people are used to seeing data displayed in the form of a list. However, wouldn't it be nice if there was a more interesting way to display the same contact data? For instance, using bigger images for the contact photos. And instead of showing everything in a list, maybe a grid is a nice alternative.

Exciting and compelling layouts drive user engagement. Users enjoy interacting with well-designed apps, and they certainly notice when you put in a bit of extra effort. Of course, merely implementing a grid layout won't automatically make your app great but when used well, users can certainly feel more at home with your app than they would if you just stick to a table view. Every app benefits from a different kind of design and layout, so collection views are no magical solution for all apps, but they indeed are a powerful tool to master.

To show contacts in a grid layout, some of the existing code has to be cleaned up. All code and designs related to the table view must be removed. That's what you should do first. When you've cleaned up the project, you're left with a great starting point to begin implementing a collection view. The conversion process has three steps:

  1. Delete all table view code.
  2. Delete the table view from the storyboard and replace it with a collection view.
  3. Add code for the collection view.

Let's start off by deleting all the code in ViewController.swift that is related to your old table view implementation. This includes removing all extensions for conformance to UITableView related protocols. After doing so, you should be left with the following implementation of ViewController.swift:

import UIKit
import Contacts

class ViewController: UIViewController {
  var contacts = [Contact]()

  override func viewDidLoad() {
    super.viewDidLoad()

    let store = CNContactStore()
    let authorizationStatus = CNContactStore.authorizationStatus(for: .contacts)

    if authorizationStatus == .notDetermined {
      store.requestAccess(for: .contacts) { [weak self] didAuthorize, error in
        if didAuthorize {
          self?.retrieveContacts(from: store)
        }
      }
    } else if authorizationStatus == .authorized  {
      retrieveContacts(from: store)
    }
  }

  func retrieveContacts(from store: CNContactStore) {
    let containerId = store.defaultContainerIdentifier()
    let predicate = CNContact.predicateForContactsInContainer(withIdentifier: containerId)
    let keysToFetch = [CNContactGivenNameKey as CNKeyDescriptor,
                       CNContactFamilyNameKey as CNKeyDescriptor,
                       CNContactImageDataAvailableKey as 
CNKeyDescriptor, CNContactImageDataKey as CNKeyDescriptor] contacts = try! store.unifiedContacts(matching: predicate, keysToFetch: keysToFetch) .map { Contact(contact: $0) } } }

You might be tempted also to remove the custom table view cell that you created in the previous chapter. You don't have to remove that for now since you can reuse the code for the collection view cell you will create later.

Now that the code is cleaned up, the user interface should also be cleaned up. Open Main.storyboard and delete the table view. You should now be left with an empty view controller that has no child views. Drag UICollectionView from the Object Library over to the view controller's view. Make sure this collection view covers the entire view, including the navigation bar that is visible at the top of the view. Next, use Reset to Suggested Constraints in the Resolve Auto Layout Issues menu to add the proper layout constraints for the collection view, just like you did before with the table view in Chapter 1UITableView Touch-Up. This will pin the collection view to the top, right, bottom, and left edges of the view controller's view.

With the collection view added to the user interface, the time has come to connect the interface and the code again. Add the following @IBOutlet to ViewController.swift so you can connect the outlet and the interface using Interface Builder:

@IBOutlet var collectionView: UICollectionView!

Back in the storyboard file, connect the new @IBOutlet to the collection view by selecting the view controller, opening the Connections Inspector, and dragging a referencing outlet from the collectionView property to the collection view you just added.

You have now successfully removed the old table view implementation, and you have swapped it out for a collection view. Of course, there is more work to be done to conclude the conversion, such as creating the custom collection view cell that will hold all of the contact information.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset