Saturday, 26 October 2019

Using @IBSegueAction with UINavigationController

I have the following setup…

enter image description here

A list of people in a UITableViewController. Tapping on a PersonCell presents a PersonViewController inside a UINavigationController

To avoid having an optional Person in the PersonViewController, I'm trying to use IBSegueActions.

My first thought was that I need one for the segue between the PeopleViewController and the PersonNavController, and the segue between the PersonNavController and the PersonViewController as follows…

class PeopleViewController: UITableViewController {

    // Table view delegate methods here

    @IBSegueAction func showPerson(_ coder: NSCoder, sender: Any?) -> PersonNavController? {
        guard let cell = sender as? PersonCell else { return nil }
        return PersonNavController(coder: coder, person: cell.person)
    }
}

class PersonNavController: UINavigationController {

    private let person: Person

    required init?(coder: NSCoder, person: Person) {
        self.person = person
        super.init(coder: coder)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    @IBSegueAction func root(_ coder: NSCoder) -> PersonViewController? {
        return PersonViewController(coder: coder, person: person)
    }
}

class PersonViewController: UIViewController {

    @IBOutlet private weak var name: UILabel!

    private let person: Person

    required init?(coder: NSCoder, person: Person) {
        self.person = person
        super.init(coder: coder)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        name.text = person.firstName
    }
}

The problem here, it turns out, is that even though you can hook up a segue action to the segue between a UINavigationController and its rootViewController, it doesn't get fired as, in the example above, the super.init(coder: coder) in PersonNavController calls PersonViewController.init(coder: NSCoder) (which isn't implemented).

Any thoughts as to how I can get this working?



from Using @IBSegueAction with UINavigationController

No comments:

Post a Comment