1. 程式人生 > >通過響應者鏈去獲取當前控制器

通過響應者鏈去獲取當前控制器

響應者鏈大家應該都知道是什麼玩意.

蘋果文件中對響應者鏈有如下一段介紹

Altering the Responder Chain
You can alter the responder chain by overriding the nextResponder property of your responder objects. When you do this, the next responder is the object that you return.

Many UIKit classes already override this property and return specific objects, including:

UIView objects. If the view is the root view of a view controller, the next responder is the view controller; otherwise, the next responder is the view’s superview.

UIViewController objects.

If the view controller’s view is the root view of a window, the next responder is the window object.

If the view controller was presented by another view controller, the next responder is the presenting view controller.

UIWindow objects. The window's next responder is the UIApplication object.

UIApplication object. The next responder is the app delegate, but only if the app delegate is an instance of UIResponder and is not a view, view controller, or the app object itself.

翻譯一下就是你可以通過呼叫nextResponder這個方法獲取當前繼承於UIResponder類物件的下一個響應者.有以下幾種情況

1.如果當前View是Window的rootView.那麼.該View的nextResponder是Window.
2.如果一個AViewController被另外一個BViewController用presented的方式展示出來的,那麼下一個響應者就是BViewController.
3.UIWindow物件的下一個響應者是UIApplication物件.
如果是UIApplication物件,並且當app delegate是UIResponder的一個物件而不是UIView,UIViewControler,或app物件本身時那麼他的下一個響應者是app delegate.

有了以上的知識我們就可以通過無限迴圈呼叫nextResponder的方式來獲取當前控制器了.

.h
- (UIViewController *)getViewControllerWithUIView:(UIView *)currentView;

.m
- (UIViewController *)getViewControllerWithUIView:(UIView *)currentView {
    for (UIView *view = currentView; view; view = view.superview) {
        UIResponder *nextResponder = [view nextResponder];
        if ([nextResponder isKindOfClass:[UIViewController class]]) {//參考上面的第二條,需要直接return.
            return (UIViewController *)nextResponder;
        }
    }
    return nil;
}

或者咱們寫一個UIView的分類後實現一個viewController方法

.h
- (UIViewController *)viewController;

.m
- (UIViewController *)viewController {
    for (UIView *view = self; view; view = view.superview) {
        UIResponder *nextResponder = [view nextResponder];
        if ([nextResponder isKindOfClass:[UIViewController class]]) {
            return (UIViewController *)nextResponder;
        }
    }
    return nil;
}