Благодаря AD Прогрессу превосходного исследования и ответу ниже, я наконец понял, что происходит с IBSegueAction
с.
Если вы подключите rootViewController
segue (или любой другой вид, предположительно) к IBSegueAction
в его UINavigationContoller
, но он не найдет его там, он будет смотреть на следующий видКонтроллер цепочки респондента, пока он не найдет IBSegueAction
с правильной подписью. Если он не найдет его, он позвонит init(with coder: NSCoder)
на rootViewController
. Если бы только это было где-то задокументировано ...
Примечания
Примечание : Это минимальный пример для иллюстрации проблемы -как передать параметры при инициализации контроллера представления, содержащегося в модальном UINavigationController
, используя IBSegueAction
. Я знаю, что это не то, как вы обычно представляете подробный вид.
Примечание 2 : я знаю, как использовать segues с prepare(for segue: UIStoryboardSegue)
. Что я хочу знать, как это, как передать необязательные параметры при инициализации контроллера представления, содержащегося в модальном UINavigationController
с использованием IBSegueAction
Примечание 3 : Я знаю, как использовать IBSegueAction
для контроллера представления, не содержащегося в UINavigationController
(например, нажатие на стек навигации)
Оригинальный вопрос
У меня есть следующие настройки…
Список людей в UITableViewController
. Нажав на PersonCell
, вы увидите PersonViewController
внутри UINavigationController
Чтобы избежать опционального Person
в PersonViewController
, я пытаюсь использовать IBSegueAction
s.
Моей первой мыслью было, что мне нужен один для перехода между PeopleViewController
и PersonNavController
и для перехода между PersonNavController
и PersonViewController
следующим образом ...
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
}
}
Проблема здесь, оказывается, в том, что даже если вы можете подключить действие перехода к переходу между UINavigationController
и его rootViewController
, оно не получаетсрабатывает, как в примере выше, super.init(coder: coder)
in PersonNavController
вызывает PersonViewController.init(coder: NSCoder)
(что не реализовано).
Есть какие-нибудь мысли о том, как я могу заставить это работать?