mah*_*udz 129 iphone debugging uiviewcontroller uiview ios
我有一个指针UIView.我如何访问它UIViewController? [self superview]是另一个UIView,但不是UIViewController,对吧?
mxc*_*xcl 261
从以下UIResponder文档nextResponder:
UIResponder类不会自动存储或设置下一个响应程序,而是默认返回nil.子类必须覆盖此方法以设置下一个响应者.UIView通过返回管理它的UIViewController对象(如果有的话)或超级视图(如果没有)来实现此方法 ; UIViewController通过返回其视图的superview来实现该方法; UIWindow返回应用程序对象,UIApplication返回nil.
因此,如果你递归视图nextResponder直到它是类型UIViewController,那么你有任何视图的父viewController.
请注意,它仍然可能没有父视图控制器.但仅当视图不是viewController视图的视图层次结构的一部分时.
Swift 3和Swift 4.1扩展:
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
}
}
Run Code Online (Sandbox Code Playgroud)
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
}
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
这个宏避免了类别污染:
#define UIViewParentController(__view) ({ \
UIResponder *__responder = __view; \
while ([__responder isKindOfClass:[UIView class]]) \
__responder = [__responder nextResponder]; \
(UIViewController *)__responder; \
})
Run Code Online (Sandbox Code Playgroud)
Dim*_*rov 40
是的,superview是包含您的视图的视图.您的视图不应该知道它的视图控制器究竟是哪个,因为这会破坏MVC原则.
另一方面,控制器知道它负责(self.view = myView)的视图,并且通常,该视图将用于处理的方法/事件委托给控制器.
通常,您应该有一个指向控制器的指针,而不是指向视图的指针,控制器可以执行某些控制逻辑,也可以将某些内容传递给其视图.
Fed*_*llo 25
@andrey在一行中回答(在Swift 4.1中测试):
extension UIResponder {
public var parentViewController: UIViewController? {
return next as? UIViewController ?? next?.parentViewController
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
let vc: UIViewController = view.parentViewController
Run Code Online (Sandbox Code Playgroud)
Leo*_*ica 22
仅出于调试目的,您可以调用_viewDelegate视图以获取其视图控制器.这是私有API,因此对App Store不安全,但对于调试它很有用.
其他有用的方法:
_viewControllerForAncestor - 获取管理superview链中视图的第一个控制器.(感谢n00neimp0rtant)_rootAncestorViewController - 获取当前在窗口中设置视图层次结构的祖先控制器.要获得对具有UIView的UIViewController的引用,您可以扩展UIResponder(它是UIView和UIViewController的超类),它允许通过响应器链并因此到达UIViewController(否则返回nil).
extension UIResponder {
func getParentViewController() -> UIViewController? {
if self.nextResponder() is UIViewController {
return self.nextResponder() as? UIViewController
} else {
if self.nextResponder() != nil {
return (self.nextResponder()!).getParentViewController()
}
else {return nil}
}
}
}
//Swift 3
extension UIResponder {
func getParentViewController() -> UIViewController? {
if self.next is UIViewController {
return self.next as? UIViewController
} else {
if self.next != nil {
return (self.next!).getParentViewController()
}
else {return nil}
}
}
}
let vc = UIViewController()
let view = UIView()
vc.view.addSubview(view)
view.getParentViewController() //provide reference to vc
Run Code Online (Sandbox Code Playgroud)
Swift 3 中快速且通用的方式:
extension UIResponder {
func parentController<T: UIViewController>(of type: T.Type) -> T? {
guard let next = self.next else {
return nil
}
return (next as? T) ?? next.parentController(of: T.self)
}
}
//Use:
class MyView: UIView {
...
let parentController = self.parentController(of: MyViewController.self)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
109179 次 |
| 最近记录: |