感谢下面的 AD Progress 研究和解答,我终于弄清了IBSegueAction
的情况。
如果您在rootViewController
中将IBSegueAction
序列(或其他类型,大概是)连接到UINavigationContoller
,但在此处找不到它,它将查看响应者链上的下一个视图控制器,直到找到具有正确签名的IBSegueAction
。如果找不到,它将在init(with coder: NSCoder)
上调用rootViewController
。如果那只是记录在某处……
注释
注意:这是一个说明问题的最小示例-使用UINavigationController
初始化模式IBSegueAction
中包含的视图控制器时如何传递参数。我知道这通常不是您呈现详细视图的方式。
注释2 :我知道如何在prepare(for segue: UIStoryboardSegue)
中使用segues。我想知道如何在使用UINavigationController
IBSegueAction
中包含的视图控制器时如何传递非可选参数。
注释3 :我知道如何使用IBSegueAction
来使用UINavigationController
中不包含的视图控制器(例如,推入导航堆栈)< / em>
原始问题
我有以下设置...
UITableViewController
中的人员列表。轻按PersonCell
会在PersonViewController
内出现UINavigationController
为了避免在Person
中使用可选的PersonViewController
,我尝试使用IBSegueAction
。
我首先想到的是,PeopleViewController
和PersonNavController
之间的安全,以及PersonNavController
和PersonViewController
之间的安全,我需要一个…… / p>
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
之间的segue进行segue动作,它也不会被触发,因为上面的示例中,super.init(coder: coder)
中的PersonNavController
调用PersonViewController.init(coder: NSCoder)
(未实现)。
关于如何使它工作的任何想法?
答案 0 :(得分:1)
为了达到想要的结果,我重新创建了一个简单的项目,该项目将链接到我的GitHub。
首先,您需要摆脱已创建到导航控制器的segue并重新创建它。
下一步选择当前模式,并使用标识符命名您的segue
接下来,您需要在第一个ViewController中定义IBSegueAction
ViewController.swift
import UIKit
class ViewController: UITableViewController {
let persons = ["Robert", "Peter", "Dave"]
var selectedPerson = 0
override func viewDidLoad() {
super.viewDidLoad()
}
@IBSegueAction
private func showPerson(coder: NSCoder, sender: Any?, segueIdentifier: String?)
-> PersonViewController? {
return PersonViewController(coder: coder, personDetails: persons[selectedPerson])
}
//MARK:- TableView Methods
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return persons.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "personCell", for: indexPath)
cell.textLabel?.text = persons[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedPerson = indexPath.row
performSegue(withIdentifier: "ShowPerson", sender: self)
}
}
然后在PersonViewController中添加init?(coder: NSCoder, personDetails: String)
的实现,如下所示。
Xcode会大喊您需要实现required init?(coder: NSCoder)
只需点击修复。
PersonViewController.swift
import UIKit
class PersonViewController: UIViewController {
//Your data passed in below as non optional constant
let personDetails: String
//The received data gets initialized below
init?(coder: NSCoder, personDetails: String) {
self.personDetails = personDetails
super.init(coder: coder)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@IBOutlet weak var personLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
personLabel.text = personDetails
}
}
下一步是在情节提要中选择ViewController的顶部,以便您可以看到三个图标。
接着,您必须选择从第二个UINavigationController到目标ViewController的Segue,这里是PersonViewController,然后将其从Segue拖回到要发送信息的ViewController的第一个黄色图标,如下面的屏幕截图所示。 Xcode将自动识别您在代码中创建的IBSegueAction的名称。
就是这样。
点击第一个View Controller中的任何单元格,您应该得到这样的结果
这是示例项目GitHub
我还找到了有关IBSegueAction here
的更多信息答案 1 :(得分:1)
我认为这不是最好的方法。
但是我不想创建
自定义导航类
初始化器
故事板
Segue
// MARK: - Segue
@available(iOS 13.0, *)
extension DrawingViewController {
@IBSegueAction private func prepareImagePickerSegue(coder: NSCoder, sender: Any?, segueIdentifier: String?) -> UIViewController? {
guard let navigationController = UINavigationController(coder: coder),
let viewController = UIStoryboard(name: "ImagePicker", bundle: nil).instantiateViewController(withIdentifier: "ImagePickerViewController") as? ImagePickerViewController else { return nil }
// Prepare the target viewController
viewController.delegate = self
// Set navigation
navigationController.setViewControllers([viewController], animated: false)
return navigationController
}
}
答案 2 :(得分:-1)