Xcode 将事件分派到swift中的父ViewController
我来自as AS3的背景,所以我可以更容易地向您展示我试图用AS3做什么。我有一个UIViewController(根),里面有一个ContainerView。我的印象是容器视图的UIViewController是UIViewController(根)的子级。我希望在子视图控制器(容器视图)上按下一个按钮,并将该事件冒泡到父视图(根UIViewController)。在AS3中,我会有这样的东西 根类创建子类Xcode 将事件分派到swift中的父ViewController,xcode,actionscript-3,swift,uiview,uicontainerview,Xcode,Actionscript 3,Swift,Uiview,Uicontainerview,我来自as AS3的背景,所以我可以更容易地向您展示我试图用AS3做什么。我有一个UIViewController(根),里面有一个ContainerView。我的印象是容器视图的UIViewController是UIViewController(根)的子级。我希望在子视图控制器(容器视图)上按下一个按钮,并将该事件冒泡到父视图(根UIViewController)。在AS3中,我会有这样的东西 根类创建子类 var childClass = new ChildClass() childCla
var childClass = new ChildClass()
childClass.addEventListener("buttonWasPressed", callThisFunction);
private function callThisFunciton(e:Event):void
{
// move the child view
TweenLite.to(childClass,1,{x:100});
}
在子类中,我有一个button函数,它将部署这个事件,该事件将冒泡到父类
dispatchEvent(new Event("buttonWasPressed", true));
我不确定如何让根VC监听该事件。因为我使用的是containerView,所以我不知道如何为那个孩子的VC建立一个出口,并倾听孩子正在做的事情。我可以控制从IB到VC的拖动,但这只是为表示容器视图的UIView创建了一个出口。当我打印一些文本时,我可以看到子视图控制器在父VC之前首先被实例化
我发现这篇文章,我认为它指向了正确的方向。
但是我得到了一个错误,很可能是因为我不确定如何在容器视图中建立从父VC到子VC的连接。我环顾四周,似乎找不到关于这个话题的太多信息
谢谢你的帮助 有两种方法:
1)使用代理协议(推荐)
a) 在子级中,创建一个委托协议,并在子级VC上创建一个可选属性,该属性将保存该委托
protocol ChildViewControllerDelegate {
}
class ChildViewController: UIViewController {
var delegate:ChildViewControllerDelegate?
}
b) 在委托协议中,创建一个在按下按钮时将被调用的方法,并在对委托调用此方法的子级中实现一个buttonwarpressed()
方法。(您需要使用情节提要中的按钮连接此方法)
c) 使父视图控制器符合子协议
class ParentViewController: UIViewController, ChildViewControllerDelegate {
func childViewControllerDidPressButton(childViewController: ChildViewController) {
// Do fun handling of child button presses!
}
}
c) 当子进程嵌入父进程时,会运行一种特殊类型的进程,称为嵌入进程。您可以在故事板中看到它-它是连接子级和父级的线:
向情节提要中的该序列添加标识符:
在父视图控制器中为其设置一个常量:
struct Constants {
static let embedSegue = "embedSegue"
}
class ParentViewController: UIViewController, ChildViewControllerDelegate {
func childViewControllerDidPressButton(childViewController: ChildViewController) {
// Do fun handling of child button presses!
}
}
d) 然后在父视图控制器中,重写prepareforsgue()
方法,并检查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) 赢
2)使用NSNotification和NSNotificationCenter
您可以将这些事件视为类似于ActionScript事件,但是它们不会像那样在视图层次结构中自动弹出。而是通过NSNotificationCenter
全局发送通知。我更喜欢仅当有多个对象需要侦听一个特定事件时才使用此选项
您可以在此处找到有关
NSNotification
和NSNotificationCenter
的更多信息:或者您可以使用静态变量,这可能是最简单的方法
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()
}
}
谢谢你非常详尽的回答!如果子视图是通过编程实现的呢??segue是如何工作的?对于这个解决方案,我的func ChildViewControllerdPressButton(childViewController:childViewController){//Do fun handling of child button press!}从未收到任何消息。有什么变化吗?这是一个好的解决方案吗??从编程角度看,这会引发什么问题(如果有的话?),从几个方面来看,这通常是个坏主意。首先,将ChildViewController耦合到ParentViewController,其他人不能使用ChildViewController。第二,如果您有两个ParentViewController实例,这将不再有效,因为只有一个静态实例。
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()
}
}