xcode 迅速将事件分派给父 ViewController
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29294005/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
dispatch event to parent ViewController in swift
提问by icekomo
I'm coming from as AS3 background so it might be easier for me to show you what I'm trying to do with AS3. I have a UIViewController(root) and inside that I have a ContainerView. I am under the impression that the container view's UIViewController is a child of the UIViewController(root). I would like a button to be pressed on the child view controller (container view) and bubble that event up to the parent(root UIViewController). In AS3 I would have something like this
我来自 AS3 背景,所以我可能更容易向您展示我想用 AS3 做什么。我有一个 UIViewController(root),里面有一个 ContainerView。我的印象是容器视图的 UIViewController 是 UIViewController(root) 的子级。我想在子视图控制器(容器视图)上按下一个按钮并将该事件冒泡到父级(root UIViewController)。在 AS3 中我会有这样的东西
Root Class creates the child class
根类创建子类
var childClass = new ChildClass()
childClass.addEventListener("buttonWasPressed", callThisFunction);
private function callThisFunciton(e:Event):void
{
// move the child view
TweenLite.to(childClass,1,{x:100});
}
And in the Child Class I have a button function that would deploy this event that would bubble up to the parent.
在子类中,我有一个按钮功能,可以部署这个事件,该事件会冒泡到父类。
dispatchEvent(new Event("buttonWasPressed", true));
What I'm not sure how to do is get the root VC listening for that event. Because I'm using a containerView I'm not sure how to set up an outlet to that child VC and listen to things that the child is doing. I can control drag from the IB to the VC, but that just created an outlet for a UIView that represents the container view. When I println some text, I can see that the child view controller is being instantiated first before the parent VC.
我不知道该怎么做是让根 VC 监听该事件。因为我使用的是 containerView,所以我不确定如何为该子 VC 设置一个插座并听取该子项正在做的事情。我可以控制从 IB 到 VC 的拖动,但这只是为代表容器视图的 UIView 创建了一个出口。当我打印一些文本时,我可以看到子视图控制器在父 VC 之前首先被实例化。
I found this post that I think is pointing in the right direction. https://craiggrummitt.wordpress.com/2014/07/14/communication-between-objects-in-objective-c-and-swift-compared-with-actionscript-part-5/
我发现这篇文章我认为指向了正确的方向。 https://craiggrummitt.wordpress.com/2014/07/14/communication-between-objects-in-objective-c-and-swift-compared-with-actionscript-part-5/
But I'm getting an error, most likely because I'm not sure how to make the connection from parent VC to child VC that's inside the container view. I have looked around and I can't seem to find much information on the topic.
但是我收到一个错误,很可能是因为我不确定如何建立从父 VC 到容器视图内的子 VC 的连接。我环顾四周,似乎找不到有关该主题的太多信息。
Thanks for the help!
谢谢您的帮助!
回答by BTSmith
There are two ways:
有两种方式:
1) Use a delegate protocol (recommended)
1)使用委托协议(推荐)
a) In your child, create a delegate protocol, and an optional property on the child VC that will hold the delegate.
a) 在您的孩子中,创建一个委托协议,并在将持有委托的子 VC 上创建一个可选属性。
protocol ChildViewControllerDelegate {
}
class ChildViewController: UIViewController {
var delegate:ChildViewControllerDelegate?
}
b) In the delegate protocol create a method that will be called when the button was pressed, and implement a buttonWasPressed()
method in the child that calls this method on the delegate. (You'll want to connect this method up with a button in the storyboard)
b) 在委托协议中创建一个将在按下按钮时buttonWasPressed()
调用的方法,并在子进程中实现一个在委托上调用此方法的方法。(您需要将此方法与故事板中的按钮连接起来)
protocol ChildViewControllerDelegate {
func childViewControllerDidPressButton(childViewController:ChildViewController)
}
class ChildViewController: UIViewController {
var delegate:ChildViewControllerDelegate?
@IBOutlet weak var button: UIButton!
@IBAction func buttonWasPressed(sender: AnyObject) {
self.delegate?.childViewControllerDidPressButton(self)
}
}
c) Make your parent view controller conform to the child protocol
c) 让你的父视图控制器符合子协议
class ParentViewController: UIViewController, ChildViewControllerDelegate {
func childViewControllerDidPressButton(childViewController: ChildViewController) {
// Do fun handling of child button presses!
}
}
c) When the child is embedded in the parent a special kind of segue is run called an embed segue. You can see it in the storyboard - it's the line that connects the child to the parent:
c) 当子进程嵌入到父进程中时,会运行一种特殊的 segue,称为 embed segue。您可以在故事板中看到它 - 这是将孩子连接到父母的线:
Add an identifier to that segue in the storyboard:
在情节提要中为该转场添加一个标识符:
And a constant for it in the parent view controller:
以及它在父视图控制器中的常量:
struct Constants {
static let embedSegue = "embedSegue"
}
class ParentViewController: UIViewController, ChildViewControllerDelegate {
func childViewControllerDidPressButton(childViewController: ChildViewController) {
// Do fun handling of child button presses!
}
}
d) Then in the parent view controller, override the prepareForSegue()
method and check if segue.identifier
matches what you had set as the identifier. If it does, then you can get a reference to the child view controller through segue.destinationViewController
. Cast this as your child view controller, then you can set the parent to be its delegate:
d) 然后在父视图控制器中,覆盖该prepareForSegue()
方法并检查是否segue.identifier
匹配您设置为标识符的内容。如果是,那么您可以通过segue.destinationViewController
. 将此作为您的子视图控制器,然后您可以将父视图设置为它的委托:
struct Constants {
static let embedSegue = "embedSegue"
}
class ParentViewController: UIViewController, ChildViewControllerDelegate {
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == Constants.embedSegue {
let childViewController = segue.destinationViewController as ChildViewController
childViewController.delegate = self
}
}
func childViewControllerDidPressButton(childViewController: ChildViewController) {
// Do fun handling of child button presses!
}
}
e) Win!
e) 赢!
2) Use NSNotification and NSNotificationCenter
2) 使用 NSNotification 和 NSNotificationCenter
You can think of these as similar to ActionScript events, however they don't automatically bubble up through the view hierarchy like AS. Instead notifications are dispatched globally through NSNotificationCenter
. I prefer to only use this when there are multiple objects that need to listen for one particular event.
您可以将它们视为类似于 ActionScript 事件,但是它们不会像 AS 那样在视图层次结构中自动冒泡。相反,通知是通过NSNotificationCenter
. 我更喜欢只在有多个对象需要侦听一个特定事件时才使用它。
You can find more information about NSNotification
and NSNotificationCenter
here: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/
你可以找到更多的信息NSNotification
,并NSNotificationCenter
在这里:https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/
回答by pravdomil
Well or you can use static variables, which is probably the most straightforward way.
好吧,或者您可以使用静态变量,这可能是最直接的方法。
class ParentViewController: UIViewController {
static var instance:ParentViewController?
override func awakeFromNib() {
self.dynamicType.instance = self
}
func parentFunction() {
print("called \(#function) in \(self.dynamicType)")
}
}
class ChildViewController: UIViewController {
func childFunction() {
ParentViewController.instance?.parentFunction()
}
override func viewDidAppear(_ animated: Bool) {
childFunction()
}
}