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
確保不會發生意外的情況。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章