little cubes

iOS Nav Controllers

When a navigation controller is used to transition the user to a different view where they need to make a selection, how can this selection data be transferred back to the main view?

ContextSection titled: Context

  • For the application I’m working on, the user needs to be able to select a category from a list. This has been implemented using a navigation controller which transitions the user from the main view to a UITableView where they are to select a category.
  • Once they have made this selection, I somehow need to transfer information about their selection back to the main view.

ResearchSection titled: Research

  • Talking with Dr. Sebern, we reached the conclusion that this is the type of problem that is generally handled with a delegate pattern. Apple’s developer website describes deletation as “a simple and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object. The delegating object keeps a reference to the other object—the delegate—and at the appropriate time sends a message to it. The message informs the delegate of an event that the delegating object is about to handle or has just handled”.

  • Tutorialspoint.com gives a (now slightly outdated) walk through of creating a delegate in objective-C here.

  • These resources in tanduem with a great deal of help from Dr. Sebern, led me to use the following steps in order to make the delegate pattern work for me:

    • Note: In the following instructions, the main view will be represented by the class mainVC, and the selection view will be represented by the class selectionVC.

    • The first step is to create a protocol which represents your delegate. This protocol will have one function, which is called by the delegating object on the delegate to inform the delegate of the change.

      • The slightly confusing part to this particular example is that the mainVC will be the delegate because it needs to receive the information (the selection), and selectionVC will be the delegating object
      • The delegate protocol should look something like this:
      protocol CategoriesControllerDelegate {
      func categorySelected(selectedCategory: String) -> Void
      }
    • After the delegate procol is implemented, a delegate property needs to be added to the delegating object (selectionVC), and initialized to nil: var delegate: CategoriesControllerDelegate? = nil

    • The delegate (mainVC) then needs to implement the delegate protocol that was created:

      class mainVC: UIViewController, CategoriesControllerDelegate{...}
      func categorySelected(selectedCategory: String) {...}
      • Whatever processing needs to be done when the selection is made should be placed in this function.
    • At some point prior to its invocation, the delegate reference contained by the delegating object needs to be set to the actual delegate object. In this example, it makes sense to do this immediately before the selection view is shown by the navigation controller. For this reason the processing is done inside of the prepareForSegue() method:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let cc = segue.destinationViewController as? CategoriesController {
    self.categoryController = cc
    cc.delegate = self
    }
    }
    • Finally, the delegating object needs to call the delegate function on it’s delegate reference whenever the necessary information is captured. In this example, this information is captured in the tableView callback method which gets called when the user selects an item from the table view:
    override func tableView(
    tableView: UITableView,
    didSelectRowAtIndexPath: Boolean,
    indexPath: NSIndexPath
    ) {
    self.delegate?.categorySelected(self.selectedItem)
    }