给定视图,如何获得它的viewController?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (16)

我有一个指针UIView。我如何访问它UIViewController[self superview]是另一个UIView,但不是UIViewController,对吗?

提问于
用户回答回答于

是的,superview是你的答案。你的视图不应该知道它的视图控制器的确切位置,因为这会打破MVC原则。

另一方面,控制器知道它负责哪个视图(self.view = myView),并且通常该视图委托用于处理控制器的方法/事件。

通常,不是指向视图的指针,而应该有一个指向你的控制器的指针,而这个指针又可以执行一些控制逻辑,或者将某些东西传递给它的视图。

用户回答回答于

从以下UIResponder文档获取nextResponder

UIResponder类不会自动存储或设置下一个响应者,而是默认返回nil。子类必须重写此方法来设置下一个响应者。UIView通过返回管理它的UIViewController对象(如果它有一个)或它的超级视图(如果没有)来实现此方法。UIViewController通过返回其视图的超级视图来实现该方法; UIWindow返回应用程序对象,并且UIApplication返回nil。

所以,如果你递归视图nextResponder直到它是类型的UIViewController,那么你有任何视图的父视图控制器。

请注意,它仍然可能没有父视图控制器。但只有当视图不是viewController视图的视图层次结构的一部分时才是如此。

Swift 3延伸:

extension UIView {
    var parentViewController: UIViewController? {
        var parentResponder: UIResponder? = self
        while parentResponder != nil {
            parentResponder = parentResponder!.next
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
        }
        return nil
    }
}

Swift 2扩展:

extension UIView {
    var parentViewController: UIViewController? {
        var parentResponder: UIResponder? = self
        while parentResponder != nil {
            parentResponder = parentResponder!.nextResponder()
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
        }
        return nil
    }
}

Objective-C类别:

@interface UIView (mxcl)
- (UIViewController *)parentViewController;
@end

@implementation UIView (mxcl)
- (UIViewController *)parentViewController {
    UIResponder *responder = self;
    while ([responder isKindOfClass:[UIView class]])
        responder = [responder nextResponder];
    return (UIViewController *)responder;
}
@end

这个宏可以避免类别污染:

#define UIViewParentController(__view) ({ \
    UIResponder *__responder = __view; \
    while ([__responder isKindOfClass:[UIView class]]) \
        __responder = [__responder nextResponder]; \
    (UIViewController *)__responder; \
})

扫码关注云+社区