Episode #270

Handling Actions from Users

Series: Refactoring to Coordinators

11 minutes
Published on May 12, 2017

This video is only available to subscribers. Get access to this video and 572 others.

In this episode, Soroush and Ben create the first delegate for a view controller in order to pull out the behavior a user might trigger by interacting with the view controller. This delegate conformance is added to our coordinator so this flow logic is in one place (and not in the view controller).

Episode Links

Adding a Start Method

The coordinator can have startup logic, so for this we'll add a new method to handle this logic:

class AppCoordinator {
  ...

  func start() {
    // startup logic
  }
}

Then from our AppDelegate:

coordinator = AppCoordinator(navigationController: nav)
coordinator?.start()

Setting up the Restaurants View Controller

We need to set our coordinator as a delegate for each view controller that is managed by the coordinator. We'll wire this up in start(). First we need a reference to it. We could create one here, but since we're using storyboards, we’ll grab it from the navigation controller the storyboard created.

func start() {
  let restaurantsVC = navigationController.topViewController as! RestaurantsViewController
}

Creating the Delegate

We don’t yet have a delegate created for our root view controller, so we’ll add one.

protocol RestaurantsViewControllerDelegate : class {
  func didSelect(restaurant: Restaurant)
}

We then need to add a weak property on our view controller of this type:

class RestaurantsViewController : UITableViewController {
  // ...

  weak var delegate: RestaurantsViewControllerDelegate?

  // ...
}

Now we just need to wire this up in our coordinator:


class AppCoordinator : RestaurantsViewControllerDelegate {
  func start() {
    let restaurantsVC = navigationController.topViewController as! RestaurantsViewController
    restaurantsVC.delegate = self
  }

  func didSelect(restaurant: Restaurant) {
  }

Creating the Detail View Controller

In order to get our detail view controller, since we're not using segues anymore, is to make sure that it has an identifier and then use storyboards to create it.

We'll create a helper function to do this for us:

// not to be confused with the similarly named view controller above...
// Note to self: better names!
class RestaurantViewController : UITableViewController {
  static func makeFromStoryboard() -> RestaurantViewController {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let identifier = String(describing: self)
    let vc = storyboard.instantiateViewController(withIdentifier: identifier) as! RestaurantViewController
    return vc
  }
}

With that in place, we can now finish our delegate implementation:

 func didSelect(restaurant: Restaurant) {
    let restaurantDetail = RestaurantViewController.makeFromStoryboard()
    restaurantDetail.restaurant = restaurant
    navigationController.pushViewController(restaurantDetail, animated: true)
 }

Lastly, make sure that the storyboard reference for RestaurantViewController has a Storyboard Identifier with the same name.

This episode uses Ios 10.3, Xcode 8.3.