来自UIResponder
的文档nextResponder
:
UIResponder 类不会自动存储或设置下一个响应者,而是默认返回 nil。子类必须重写此方法才能设置下一个响应者。UIView 通过返回管理它的 UIViewController 对象(如果有)或其超级视图(如果没有)来实现此方法; UIViewController 通过返回其视图的超级视图来实现该方法; UIWindow返回应用程序对象,UIApplication返回nil。
所以,如果你递归一个视图nextResponder
直到它是类型UIViewController
,那么你就有了任何视图的父视图控制器。
请注意,它仍然可能not有一个父视图控制器。但前提是该视图不属于 viewController 的视图层次结构的一部分。
斯威夫特 3 和斯威夫特 4.1扩大:
extension UIView {
var parentViewController: UIViewController? {
// Starts from next (As we know self is not a UIViewController).
var parentResponder: UIResponder? = self.next
while parentResponder != nil {
if let viewController = parentResponder as? UIViewController {
return viewController
}
parentResponder = parentResponder?.next
}
return nil
}
}
斯威夫特 2 扩展:
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self.nextResponder()
while parentResponder != nil {
if let viewController = parentResponder as? UIViewController {
return viewController
}
parentResponder = parentResponder!.nextResponder()
}
return nil
}
}
Objective-C 类别:
@interface UIView (mxcl)
- (UIViewController *)parentViewController;
@end
@implementation UIView (mxcl)
- (UIViewController *)parentViewController {
UIResponder *responder = [self nextResponder];
while (responder != nil) {
if ([responder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)responder;
}
responder = [responder nextResponder];
}
return nil;
}
@end
这个宏避免了类别污染:
#define UIViewParentController(__view) ({ \
UIResponder *__responder = __view; \
while ([__responder isKindOfClass:[UIView class]]) \
__responder = [__responder nextResponder]; \
(UIViewController *)__responder; \
})