如何从 ContainerView 更新父 view/viewController 的元素?
How do I update elements of the parent view/viewController from a ContainerView?
我有一个 ViewController,它包含一个 ContainerView。
因此,我为 ViewController() 添加了一个 class,为 ContainerViews ViewController() 添加了一个 class。为了更好地说明它,我附上了一张我的 storboard 场景的照片:
当我单击 ContainerView 中的按钮时,我想用不同的文本更新标签,我该如何实现?重要提示:ContainerViews 按钮是单独 ViewController 中的 IBAction,我想更新单独 ViewController() class 中的 IBOutlet。非常感谢帮助!!!
在容器视图中获取 parent 视图控制器并将其转换为您的 parent 控制器的类型(如
thefredelement 的评论)会起作用,但是它有一些缺点。
- 你的容器视图真的应该是恰好是
MVC本身。作为一种观点,它不应该知道谁在控制它,
然而,它可能知道它有一个可以发送的委托
消息到。例如,UITextView 是否知道它是 child
特定 class 的视图控制器?不,但它知道它可能
有一个可以向其发送消息的委托。
- 您不能将此视图控制器作为任何其他视图控制器的 child 重复使用,因为它与 parent class
紧密耦合
- 只需将收到的 parent 转换为您的 parent 类型,您就可以绕过类型检查。
所以 "quick fix" 可能会按照评论中的建议去做,但是,我提供这个答案作为建议,因为我认为在长期 运行 中应该如何处理这个问题。希望其他人觉得它有用。我知道经历整个思考过程对我很有帮助。
理想情况下,我认为您应该在 ContainerViewController 中声明一个变量,该变量要么是您的 parent 视图控制器的 Class,或者更好的是您的 parent 控制器将遵循的协议到。然后在准备 parent 视图控制器的 segue 时,您将设置此变量。
同时,您的 parent 应该(或至少可以)将变量声明为您的容器视图类型或容器将遵守的其他协议。然后也在准备 parent 的 segue 中,获取 Container 视图控制器的句柄并将其存储在您声明的变量中。
所以像这样:
在您的 ContainerViewController 中
var myContainerViewDelegate: ParentViewControllerOrProtocol
在您的 parent 视图控制器中
weak var myChildViewOutlet: ChildViewControllerOrProtocol
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "embededSegueToChild" {
if let dvc = segue.destinationViewController.contentViewController as? ChildViewControllerOrProtocol {
dvc.myContainerViewDelegate = self
myChildViewOutlet = dvc
}
}
这样你的 ContainerViewController 看起来像视图 object(我认为这是它应该考虑的样子),而 myChildViewOutlet 变量是你到那个视图的出口(它可能应该很弱)。
容器中的 myContainerViewDelegate 引用实质上将您的 parent 设置为容器视图控制器的委托。
现在两个视图控制器都有彼此的句柄
我有一个 ViewController,它包含一个 ContainerView。
因此,我为 ViewController() 添加了一个 class,为 ContainerViews ViewController() 添加了一个 class。为了更好地说明它,我附上了一张我的 storboard 场景的照片:
当我单击 ContainerView 中的按钮时,我想用不同的文本更新标签,我该如何实现?重要提示:ContainerViews 按钮是单独 ViewController 中的 IBAction,我想更新单独 ViewController() class 中的 IBOutlet。非常感谢帮助!!!
在容器视图中获取 parent 视图控制器并将其转换为您的 parent 控制器的类型(如 thefredelement 的评论)会起作用,但是它有一些缺点。
- 你的容器视图真的应该是恰好是 MVC本身。作为一种观点,它不应该知道谁在控制它, 然而,它可能知道它有一个可以发送的委托 消息到。例如,UITextView 是否知道它是 child 特定 class 的视图控制器?不,但它知道它可能 有一个可以向其发送消息的委托。
- 您不能将此视图控制器作为任何其他视图控制器的 child 重复使用,因为它与 parent class 紧密耦合
- 只需将收到的 parent 转换为您的 parent 类型,您就可以绕过类型检查。
所以 "quick fix" 可能会按照评论中的建议去做,但是,我提供这个答案作为建议,因为我认为在长期 运行 中应该如何处理这个问题。希望其他人觉得它有用。我知道经历整个思考过程对我很有帮助。
理想情况下,我认为您应该在 ContainerViewController 中声明一个变量,该变量要么是您的 parent 视图控制器的 Class,或者更好的是您的 parent 控制器将遵循的协议到。然后在准备 parent 视图控制器的 segue 时,您将设置此变量。
同时,您的 parent 应该(或至少可以)将变量声明为您的容器视图类型或容器将遵守的其他协议。然后也在准备 parent 的 segue 中,获取 Container 视图控制器的句柄并将其存储在您声明的变量中。
所以像这样:
在您的 ContainerViewController 中
var myContainerViewDelegate: ParentViewControllerOrProtocol
在您的 parent 视图控制器中
weak var myChildViewOutlet: ChildViewControllerOrProtocol
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "embededSegueToChild" {
if let dvc = segue.destinationViewController.contentViewController as? ChildViewControllerOrProtocol {
dvc.myContainerViewDelegate = self
myChildViewOutlet = dvc
}
}
这样你的 ContainerViewController 看起来像视图 object(我认为这是它应该考虑的样子),而 myChildViewOutlet 变量是你到那个视图的出口(它可能应该很弱)。
容器中的 myContainerViewDelegate 引用实质上将您的 parent 设置为容器视图控制器的委托。
现在两个视图控制器都有彼此的句柄