在swift中将调度事件发送到父ViewController

ice*_*omo 11 xcode actionscript-3 uiview uicontainerview swift

我来自AS3背景,因此我可能更容易向您展示我正在尝试使用AS3做什么.我有一个UIViewController(root),里面有一个ContainerView.我的印象是容器视图的UIViewController是UIViewController(root)的子代.我希望在子视图控制器(容器视图)上按下一个按钮,并将该事件冒泡到父级(根UIViewController).在AS3中我会有类似的东西

Root 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});

}
Run Code Online (Sandbox Code Playgroud)

在Child Class中,我有一个按钮功能,可以部署这个会冒泡到父级的事件.

dispatchEvent(new Event("buttonWasPressed", true));
Run Code Online (Sandbox Code Playgroud)

我不确定该怎么做是让root VC监听该事件.因为我正在使用一个容器视图,所以我不知道如何为那个孩子VC建立一个出口并听取孩子正在做的事情.我可以控制从IB到VC的拖动,但这只是为代表容器视图的UIView创建了一个插座.当我打印一些文本时,我可以看到子视图控制器首先在父VC之前被实例化.

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

但是我收到了一个错误,很可能是因为我不确定如何从父VC到容器视图中的子VC建立连接.我环顾四周,似乎无法找到有关该主题的更多信息.

谢谢您的帮助!

BTS*_*ith 32

有两种方法:

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

a)在您的孩子中,创建一个委托协议,以及将保存该委托的子VC上的可选属性.

protocol ChildViewControllerDelegate {

}

class ChildViewController: UIViewController {

    var delegate:ChildViewControllerDelegate?
}
Run Code Online (Sandbox Code Playgroud)

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

c)使您的父视图控制器符合子协议

class ParentViewController: UIViewController, ChildViewControllerDelegate {

    func childViewControllerDidPressButton(childViewController: ChildViewController) {
        // Do fun handling of child button presses!
    }
}
Run Code Online (Sandbox Code Playgroud)

c)当孩子嵌入父母时,会运行一种称为嵌入segue的特殊segue.您可以在故事板中看到它 - 它是将孩子连接到父母的线:

显示选择的嵌入segue

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

显示嵌入segue的设置,并设置自定义标识符

并且父视图控制器中的常量为:

struct Constants {
    static let embedSegue = "embedSegue"
}

class ParentViewController: UIViewController, ChildViewControllerDelegate {

    func childViewControllerDidPressButton(childViewController: ChildViewController) {
        // Do fun handling of child button presses!
    }
}
Run Code Online (Sandbox Code Playgroud)

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!
    }
}
Run Code Online (Sandbox Code Playgroud)

e)赢!

2)使用NSNotification和NSNotificationCenter

您可以将它们视为与ActionScript事件类似,但它们不会像AS那样自动在视图层次结构中冒泡.而是通过全局调度通知NSNotificationCenter.当有多个对象需要监听某个特定事件时,我更喜欢使用它.

你可以找到更多的信息NSNotification,并NSNotificationCenter在这里:https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/

  • 对于此解决方案,我的func childViewControllerDidPressButton(childViewController:ChildViewController){//对子按钮的按下进行有趣的处理!}永远不会收到任何东西。有什么改变吗? (2认同)

pra*_*mil 5

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

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()
    }
}
Run Code Online (Sandbox Code Playgroud)