UINavigationController
,它的根 View Controller 是一个普通的 UITableViewController
。表格 View 显示了一个字母列表。 ContainerViewController
。它包含一个嵌入的 ContentViewController
,其作用是在屏幕上显示选定的字母。 内容 View Controller 将要显示的字母存储为属性
letter: String
,该属性应在其 View 推送到屏幕上之前设置。class ContentViewController: UIViewController {
var letter = "-"
@IBOutlet private weak var label: UILabel!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
label.text = letter
}
}
相反,容器 View Controller 不应该知道关于这封信的任何信息(内容不知道),因为我试图将它构建为尽可能可重用。
class ContainerViewController: UIViewController {
var contentViewController: ContentViewController? {
return childViewControllers.first as? ContentViewController
}
}
我尝试在我的表 View Controller 中相应地编写
prepareForSegue()
:override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let containerViewController = segue.destinationViewController as? ContainerViewController {
let indexPath = tableView.indexPathForCell(sender as! UITableViewCell)!
let letter = letterForIndexPath(indexPath)
containerViewController.navigationItem.title = "Introducing \(letter)"
// Not executed:
containerViewController.contentViewController?.letter = letter
}
}
但是
contentViewController
在调用此方法时尚未创建 ,并且从未设置过 letter 属性。值得一提的是,当直接在内容 View Controller 上设置 segue 的目标 View Controller 时,这确实有效——在相应地更新
prepareForSegue()
之后。你知道如何实现这一目标吗?
最佳答案
其实我觉得正确的解决方案是依靠内容 View 的 程序化实例化,这是我经过深思熟虑后选择的。
以下是我遵循的步骤:
ContainerViewController
的推送segue。当用户点击一个单元格时它仍然会被执行。 ContentViewController
的嵌入转场,并在我的类(class)中向该容器 View 添加了一个 IB Outlet。 ContentViewController
,以便我们可以在适当的时候以编程方式实例化它。 ContainerViewController.swift
看起来像(大部分代码安装并删除了布局约束):class ContainerViewController: UIViewController {
var contentViewController: UIViewController? {
willSet {
setContentViewController(newValue)
}
}
@IBOutlet private weak var containerView: UIView!
private var constraints = [NSLayoutConstraint]()
override func viewDidLoad() {
super.viewDidLoad()
setContentViewController(contentViewController)
}
private func setContentViewController(newContentViewController: UIViewController?) {
guard isViewLoaded() else { return }
if let previousContentViewController = contentViewController {
previousContentViewController.willMoveToParentViewController(nil)
containerView.removeConstraints(constraints)
previousContentViewController.view.removeFromSuperview()
previousContentViewController.removeFromParentViewController()
}
if let newContentViewController = newContentViewController {
let newView = newContentViewController.view
addChildViewController(newContentViewController)
containerView.addSubview(newView)
newView.frame = containerView.bounds
constraints.append(newView.leadingAnchor.constraintEqualToAnchor(containerView.leadingAnchor))
constraints.append(newView.topAnchor.constraintEqualToAnchor(containerView.topAnchor))
constraints.append(newView.trailingAnchor.constraintEqualToAnchor(containerView.trailingAnchor))
constraints.append(newView.bottomAnchor.constraintEqualToAnchor(containerView.bottomAnchor))
constraints.forEach { $0.active = true }
newContentViewController.didMoveToParentViewController(self)
}
} }
LetterTableViewController
类中,我实例化并设置了我的内容 View Controller ,它被添加到容器的 subview Controller 中。这是代码:override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let containerViewController = segue.destinationViewController as? ContainerViewController {
let indexPath = tableView.indexPathForCell(sender as! UITableViewCell)!
let letter = letterForIndexPath(indexPath)
containerViewController.navigationItem.title = "Introducing \(letter)"
if let viewController = storyboard?.instantiateViewControllerWithIdentifier("ContentViewController"),
let contentViewController = viewController as? ContentViewController {
contentViewController.letter = letter
containerViewController.contentViewController = contentViewController
}
}
}
这非常有效,使用完全与内容无关的容器 View Controller 。顺便说一句,它曾经是在
UITabBarController
委托(delegate)方法中实例化 UINavigationController
或 appDidFinishLaunching:withOptions:
及其子代的方式。我能看到的唯一缺点是:UI 流程 ne 不再明确出现在 storyboard 上。
关于ios - 将数据传递给嵌入在容器 View Controller 中的 View Controller ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36570168/