IOS 笔记 - navigationController delegate 劫持

UINavigationControllerDelegate 的定义如下,以及两个常用的方法(在IOS7中又新增了几个新的方法)
UIUNavigationController.h
……
@protocol UINavigationControllerDelegate < NSObject >

@optional

// Called when the navigation controller shows a new top view controller via a push, pop or setting of the view controller stack.
- (
void )navigationController:( UINavigationController *)navigationController willShowViewController:( UIViewController *)viewController animated:( BOOL )animated;
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
……

当在某个NavigationController或者这个NavigationController的孩子节点下面设置其delegate的时候,这两个方法会进行回调(如果重写了这两个方法,或者其中的一个)

我们把NavigationController以及其孩子节点组成的节点集合成为NavigationController链(真实的结构是一个栈)
当在一条 NavigationController链上的多个节点都设置了delegate。
比如有一条NavigationController链上的节点如下:NavigationController->GrowUpShowViewController(Root)->DetailInfoViewController->TalkingViewController
分别在 GrowUpShowViewController和 TalkingViewController上都设置了delegate

GrowUpShowViewController’s Delegate

viewDidload 方法中写上回调:
self . navigationController . delegate = self ;

回调方法:
#pragma mark - UINavigationControllerDelegate

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if (viewController == self) {
        //隐藏父视图的TabBar
        RootViewController *tabBarController = (RootViewController *)self.navigationController.tabBarController;
        [tabBarController hiddenTabBar];
       
        //加载自定义的TabBar
        [self loadCustomTabBarView];
       
        [self initHeaderView];
    }else{
        RootViewController *tabBarController = (RootViewController *)self.navigationController.tabBarController;
        [tabBarController hiddenTabBar];
        [self hiddenTabBar];
    }
}

TalkingViewController’s Delegate

viewDidload 方法中写上回调:
self . navigationController . delegate = self ;

回调方法:
#pragma mark - UINavigationControllerDelegate

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    // 查看WEB内容
    if ([viewController isKindOfClass:[NavShowSchoolDesVC class]]) {
        RootViewController *tabBarController = (RootViewController *)self.navigationController.tabBarController;
        [tabBarController hiddenTabBar];//隐藏主界面的TabBar
    }else if(viewController == self && initMessage!=nil) {
        RootViewController *tabBarController = (RootViewController *)self.navigationController.tabBarController;
        [tabBarController showTabBar];//显示主界面的TabBar
    }
}

那么问题随之来了,哪个Controller的方法会收到回调信息,或者是都会收到回调信息

测试发现,在链执行到这里的时候
NavigationController->GrowUpShowViewController(Root)->DetailInfoViewController->
GrowUpShowViewController’s Delegate 的方法会执行

当链执行到这里的时候
TalkingViewController
TalkingViewController’s Delegate 会执行

接着回退到之前的页面
NavigationController->GrowUpShowViewController(Root)->DetailInfoViewController->TalkingViewController

发现只有
TalkingViewController’s Delegate 会执行

得到了结论:使用 self . navigationController . delegate设置的Delegate是对于当前的NavigationController链是全局的,以当前链上最后一个Controller设置的delegate为准。

解决方法:
viewWillAppear方法设置delegate=self,在 viewDidDisappear方法设置delegate=nil
确保不会发生意外的情况。

你可能感兴趣的:(IOS)