在 swift 中将事件分派到 parent ViewController

dispatch event to parent ViewController in swift

我来自 AS3 背景,所以我可能更容易向您展示我正在尝试使用 AS3 做什么。我有一个 UIViewController(root),里面有一个 ContainerView。我的印象是容器视图的 UIViewController 是 UIViewController(root) 的 child。我想在 child 视图控制器(容器视图)上按下一个按钮,然后将该事件冒泡到 parent(root UIViewController)。在 AS3 中我会有这样的东西

根 Class 创建 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});

}

在 Child Class 中,我有一个按钮函数可以部署此事件,该事件会冒泡到 parent。

dispatchEvent(new Event("buttonWasPressed", true));

我不确定如何让根 VC 监听那个事件。因为我使用的是 containerView,所以我不确定如何为 child VC 设置出口并听取 child 正在做的事情。我可以控制从 IB 到 VC 的拖动,但这只是为表示容器视图的 UIView 创建了一个出口。当我打印一些文本时,我可以看到 child 视图控制器在 parent VC.

之前首先被实例化

我发现这个 post 我认为指向正确的方向。 https://craiggrummitt.wordpress.com/2014/07/14/communication-between-objects-in-objective-c-and-swift-compared-with-actionscript-part-5/

但是我收到一个错误,很可能是因为我不确定如何建立从 parent VC 到 child VC 的连接容器视图。我环顾四周,似乎找不到太多关于该主题的信息。

感谢您的帮助!

有两种方式:

1) 使用委托协议(推荐)

a) 在您的 child 中,创建一个委托协议,并在 child VC 上创建一个可选的 属性 来保存委托。

protocol ChildViewControllerDelegate {

}

class ChildViewController: UIViewController {

    var delegate:ChildViewControllerDelegate?
}

b) 在委托协议中创建一个将在按下按钮时调用的方法,并在 child 中实现一个 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) 让你的 parent 视图控制器符合 child 协议

class ParentViewController: UIViewController, ChildViewControllerDelegate {

    func childViewControllerDidPressButton(childViewController: ChildViewController) {
        // Do fun handling of child button presses!
    }
}

c) 当 child 嵌入到 parent 中时,一种特殊的转场是 运行,称为嵌入转场。你可以在故事板中看到它——它是连接 child 和 parent 的线:

在故事板中为该 segue 添加标识符:

并且在 parent 视图控制器中有一个常量:

struct Constants {
    static let embedSegue = "embedSegue"
}

class ParentViewController: UIViewController, ChildViewControllerDelegate {

    func childViewControllerDidPressButton(childViewController: ChildViewController) {
        // Do fun handling of child button presses!
    }
}

d) 然后在 parent 视图控制器中,覆盖 prepareForSegue() 方法并检查 segue.identifier 是否与您设置的标识符匹配。如果是,那么您可以通过 segue.destinationViewController 获得对 child 视图控制器的引用。将其作为您的 child 视图控制器,然后您可以将 parent 设置为它的委托:

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) 赢了!

2) 使用 NSNotification 和 NSNotificationCenter

您可以将这些视为类似于 ActionScript 事件,但它们不会像 AS 那样自动在视图层次结构中向上冒泡。相反,通知是通过 NSNotificationCenter 在全球范围内发送的。我更喜欢只在有多个 objects 需要监听一个特定事件时才使用它。

您可以在此处找到有关 NSNotificationNSNotificationCenter 的更多信息:https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/

嗯,或者你可以使用静态变量,这可能是最直接的方法。

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()
    }
}