在 segue 之间推送信息是行不通的
Pushing information between segues won't work
我有意见A和B。
视图 A 有两个不同的视图 B,我的 prepareForSegue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
let nextView = segue.destination as! LabelWithTextView
nextView.HeaderLabel = UILabel()
nextView.TextToDisplay = UITextView()
if segue.identifier == "segue_to_tc"
{
nextView.HeaderLabel.text = "Terms and Conditions"
nextView.TextToDisplay.text = "Terms and Conditions agreement will be displayed here once available."
}
else if segue.identifier == "segue_to_p"
{
nextView.HeaderLabel.text = "Privacy Policy"
nextView.TextToDisplay.text = "Privacy Policy agreement will be displayed here once available."
}
}
和视图 B:
class LabelWithTextView: UIViewController
{
var HeaderLabel: UILabel!
var TextToDisplay: UITextView!
override func viewDidLoad()
{
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(false, animated: true)
TextToDisplay.isEditable = false
self.view.bringSubview(toFront: HeaderLabel)
self.view.bringSubview(toFront: TextToDisplay)
}
}
但是当我执行 segue 时,没有显示任何信息:
在之前的迭代中,我的故事板中有两个带有出口的对象,它们也没有改变。如果我在 PrepareForSegue 中取出 HeaderLabel 和 TextToDisplay 实例化,它会崩溃,因为它们为零。
有没有办法删除 PrepareForSegue 中的实例化?
如何正确传递信息?
它清楚地表明你有一个导航控制器作为你的 segue 的目的地,所以你可以做的是在你的 prepareForSegue 中将目的地转换为 UINavigationController 然后使用它的 topViewController 作为你的目的地
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
let nextView = segue.destination as? UINavigationController
let destinationController = nextView?.topViewController as! LabelWithTextView
//proceed with what you're doing with destinationController Instance
}
您在问题中包含的代码不起作用,因为您从未在 LabelWithTextView
.[=24= 中添加 HeaderLabel
和 TextToDisplay
作为 self.view
的子视图]
你的“上一次迭代”,其中 HeaderLabel
和 TextToDisplay
在故事板中,可能没有工作,因为你试图访问 HeaderLabel
和 TextToDisplay
在它们被加载之前。当 UIKit 执行 segue 时,它会实例化目标视图控制器并在 加载目标视图控制器的视图之前发送 prepareForSegue:sender:
消息 。
直接访问目标视图控制器的视图层次结构通常不是源视图控制器的工作。
解决此问题的一种常见方法是引入模型对象并将其传递到目的地。例如,我们可以创建一个 struct
来保存策略详细信息:
struct PolicyModel {
var title: String
var body: String
}
然后我们可以给目标视图控制器一个属性这种类型,并在视图加载后使用属性配置视图:
class PolicyViewController: UIViewController {
var policy = PolicyModel(title: "", body: "") {
didSet { updateViews() }
}
@IBOutlet var titleLabel: UILabel!
@IBOutlet var bodyView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
updateViews()
}
private func updateViews() {
guard isViewLoaded else { return }
titleLabel.text = policy.title
bodyView.text = policy.body
}
}
最后,在segue源中,我们可以根据segue标识符设置目标的policy
:
class SourceViewController: UIViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch (segue.identifier ?? "", segue.destination) {
case ("TermsAndConditions", let destination as PolicyViewController):
destination.policy = PolicyModel(title: "Terms and Conditions", body: "Blah blah blah")
case ("Privacy", let destination as PolicyViewController):
destination.policy = PolicyModel(title: "Privacy Policy", body: "Blah blah blah")
default: super.prepare(for: segue, sender: sender)
}
}
}
我有意见A和B。
视图 A 有两个不同的视图 B,我的 prepareForSegue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
let nextView = segue.destination as! LabelWithTextView
nextView.HeaderLabel = UILabel()
nextView.TextToDisplay = UITextView()
if segue.identifier == "segue_to_tc"
{
nextView.HeaderLabel.text = "Terms and Conditions"
nextView.TextToDisplay.text = "Terms and Conditions agreement will be displayed here once available."
}
else if segue.identifier == "segue_to_p"
{
nextView.HeaderLabel.text = "Privacy Policy"
nextView.TextToDisplay.text = "Privacy Policy agreement will be displayed here once available."
}
}
和视图 B:
class LabelWithTextView: UIViewController
{
var HeaderLabel: UILabel!
var TextToDisplay: UITextView!
override func viewDidLoad()
{
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(false, animated: true)
TextToDisplay.isEditable = false
self.view.bringSubview(toFront: HeaderLabel)
self.view.bringSubview(toFront: TextToDisplay)
}
}
但是当我执行 segue 时,没有显示任何信息:
在之前的迭代中,我的故事板中有两个带有出口的对象,它们也没有改变。如果我在 PrepareForSegue 中取出 HeaderLabel 和 TextToDisplay 实例化,它会崩溃,因为它们为零。
有没有办法删除 PrepareForSegue 中的实例化? 如何正确传递信息?
它清楚地表明你有一个导航控制器作为你的 segue 的目的地,所以你可以做的是在你的 prepareForSegue 中将目的地转换为 UINavigationController 然后使用它的 topViewController 作为你的目的地
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
let nextView = segue.destination as? UINavigationController
let destinationController = nextView?.topViewController as! LabelWithTextView
//proceed with what you're doing with destinationController Instance
}
您在问题中包含的代码不起作用,因为您从未在 LabelWithTextView
.[=24= 中添加 HeaderLabel
和 TextToDisplay
作为 self.view
的子视图]
你的“上一次迭代”,其中 HeaderLabel
和 TextToDisplay
在故事板中,可能没有工作,因为你试图访问 HeaderLabel
和 TextToDisplay
在它们被加载之前。当 UIKit 执行 segue 时,它会实例化目标视图控制器并在 加载目标视图控制器的视图之前发送 prepareForSegue:sender:
消息 。
直接访问目标视图控制器的视图层次结构通常不是源视图控制器的工作。
解决此问题的一种常见方法是引入模型对象并将其传递到目的地。例如,我们可以创建一个 struct
来保存策略详细信息:
struct PolicyModel {
var title: String
var body: String
}
然后我们可以给目标视图控制器一个属性这种类型,并在视图加载后使用属性配置视图:
class PolicyViewController: UIViewController {
var policy = PolicyModel(title: "", body: "") {
didSet { updateViews() }
}
@IBOutlet var titleLabel: UILabel!
@IBOutlet var bodyView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
updateViews()
}
private func updateViews() {
guard isViewLoaded else { return }
titleLabel.text = policy.title
bodyView.text = policy.body
}
}
最后,在segue源中,我们可以根据segue标识符设置目标的policy
:
class SourceViewController: UIViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch (segue.identifier ?? "", segue.destination) {
case ("TermsAndConditions", let destination as PolicyViewController):
destination.policy = PolicyModel(title: "Terms and Conditions", body: "Blah blah blah")
case ("Privacy", let destination as PolicyViewController):
destination.policy = PolicyModel(title: "Privacy Policy", body: "Blah blah blah")
default: super.prepare(for: segue, sender: sender)
}
}
}