简体   繁体   English

iOS 响应链和事件

[英]iOS Responder Chain and Events

I'm a little confused.我有点困惑。 There are two UIViewControllers in UINavagationController 's stack. UINavagationController的堆栈中有两个UIViewControllers I try to call the method of first UIViewController within the second UIViewController .我尝试在第二个UIViewController调用第一个UIViewController的方法。 See code below见下面的代码

class VC1: UIViewController {

    @objc func method1() {
        //not called after tap button
    }
}

class VC2: UIViewController {

    let button = UIButton()

    override func viewDidLoad() {
        super.viewDidLoad()

        button.addTarget(nil, action: #selector(VC1.method1), for: .touchUpInside)
    }
}

But method1 isn't called when I tap on the button.但是当我点击按钮时不会调用方法1。 What's the problem?有什么问题?

The responder chain is based on superviews and parent view controllers.响应者链基于超级视图和父视图控制器。 So VC1 is not up the responder chain from VC2.所以 VC1 不在 VC2 的响应者链上。 The responder chain from VC2 leads to its parent (the UINavigationController);来自 VC2 的响应者链通向其父级(UINavigationController); it does not go by way of any other children of the UINavigationController.它不会通过 UINavigationController 的任何其他子项。

The responder chain, starting from button , goes through button 's ancestor views and view controllers.响应者链,从button开始,经过button的祖先视图和视图控制器。 Since VC1 and VC2 are separate items in the navigation controller's stack, VC1 is not an ancestor of VC2.由于 VC1 和 VC2 是导航控制器堆栈中的独立项,因此 VC1 不是 VC2 的祖先。 They are more like siblings of each other.他们更像是彼此的兄弟姐妹。 So VC1 is not in button 's responder chain.所以 VC1 不在button的响应链中。

You could just set VC1 as the target of the button action:您可以将 VC1 设置为按钮操作的目标:

let vc1: VC1 = ...
button.addTarget(vc1, action: #selector(VC1.method1), for: .touchUpInside)

But that means VC2 needs reference to the existing VC1 instance.但这意味着 VC2 需要引用现有的 VC1 实例。 How do you get that reference?你怎么得到这个参考? It depends on how you created VC2 and pushed it on the navigation stack.这取决于您如何创建 VC2 并将其推送到导航堆栈上。

If VC1 creates VC2 in code, then VC1 can just give the new VC2 a reference to self (the VC1) when creating the VC2.如果 VC1 在代码中创建了 VC2,那么在创建 VC2 时,VC1 可以只给新的 VC2 一个对self (VC1)的引用。

If you have a storyboard segue from VC1 that pushes VC2 onto the stack, then you need to implement prepare(for: UIStoryboardSegue, sender:) in VC1, and in that method you need to hand self (VC1) to the destination of the segue (VC2).如果您有来自 VC1 的故事板 segue 将 VC2 推入堆栈,那么您需要在 VC1 中实现prepare(for: UIStoryboardSegue, sender:) ,并且在该方法中您需要将self (VC1) 交给 segue 的目的地(VC2)。

  • When you push, the relationship is between the pushedViewController and navigationController.推送时,是pushViewController 和navigationController 之间的关系。
  • When you modally present, the relationship is between the presentedViewController and UIWindow .当你以模态呈现时,关系是在presentedViewControllerUIWindow之间。 Understandably there is a relationship between the presenting and presented view controllers, but it's just a matter of them having references to one another.可以理解的是,呈现和呈现的视图控制器之间存在一种关系,但这只是它们相互引用的问题。 Their not hooked up through the responder chain pipeline...他们没有通过响应者链管道连接......
  • Only when a viewController is made a childViewController of anotherViewController then their responder chain is hooked in the way you think meaning the childViewController's nextResponder becomes its 'parentViewController'只有当 viewController 成为 anotherViewController 的 childViewController 时,它们的响应者链才会以您认为的方式挂钩,这意味着 childViewController 的nextResponder成为其“parentViewController”

——— ———

From nextResponder docs :来自nextResponder文档

For example, UIView implements this method and returns the UIViewController object that manages it (if it has one) or its superview (if it doesn't).例如,UIView 实现了这个方法并返回管理它的 UIViewController 对象(如果有的话)或者它的超级视图(如果没有的话)。 UIViewController similarly implements the method and returns its view's superview. UIViewController 类似地实现了该方法并返回其视图的超视图。 UIWindow returns the application object. UIWindow 返回应用程序对象。 The shared UIApplication object normally returns nil, but it returns its app delegate if that object is a subclass of UIResponder and has not already been called to handle the event.共享的 UIApplication 对象通常返回 nil,但如果该对象是 UIResponder 的子类并且尚未被调用来处理事件,则它会返回其应用程序委托。

Reading this we understand that neither the presentingViewController nor the pushingViewController are a viewController's superview读到这里我们明白presentingViewController 和pushViewController 都不是viewController 的superview

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM