iOS讓導航返回按鈕可以選擇性的pop

需求是從不同頁面push過來要做不同的pop,有的直接返回上一級,有的要返回到rootViewController。

介紹我想到的有兩種方式和遇到的問題以及解決的辦法。


方式一:

自定義一個按鈕,添加點擊事件,在事件中去自由的pop,然后把這個自定義按鈕設置為導航欄的self.navigationItem.leftBarButtonItem。

存在的問題:左滑返回的手勢失效了。

解決辦法:
第一步:在RootViewController的viewDidAppear中把self.navigationController.interactivePopGestureRecognizer.enabled = NO;

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    // 解決自定義返回按鈕影響左滑手勢的問題
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}

第二步:
在push控制器前調用

    // 解決自定義返回按鈕影響左滑手勢的問題
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
    {
        self.navigationController.interactivePopGestureRecognizer.enabled = YES;
        self.navigationController.interactivePopGestureRecognizer.delegate = nil;
    }

方式二:

但是我的項目中用的都是系統的返回按鈕,如果自定義的話樣式會不統一,所以要用系統的返回按鈕。

存在的問題:怎么攔截導航欄返回按鈕事件

解決辦法
聲明:此方法網上流傳已久,我只是搬運工,記錄下來。具體的作者我也不知道是誰,向作者致敬。@此方法的第一位分享者
可能是http://stackoverflow.com/questions/1214965/setting-action-for-back-button-in-navigation-controller/19132881#19132881

可以為 UINavigatonController 創建一個 Category,來定制navigationBar: shouldPopItem: 的邏輯。這里需要注意的是,我們不需要去設置 delegate,因為 UINavigatonController 自帶的 UINavigationBar 的 delegate 就是導航欄本身。這樣還有個問題就是,那在實際的 Controller 里面怎么控制呢?因此同樣需要對 UIViewController 添加一個 Protocol,這樣在 Controller 中使用該 Protocol 提供的方法即可進行控制了,代碼如下
.h中:

@protocol BackButtonHandlerProtocol <NSObject>
@optional
// 重寫下面的方法以攔截導航欄返回按鈕點擊事件,返回 YES 則 pop,NO 則不 pop
-(BOOL)navigationShouldPopOnBackButton;
@end

@interface UIViewController (BackButtonHandler) <BackButtonHandlerProtocol>

@end

.m中

@implementation UIViewController (BackButtonHandler)

@end


@implementation UINavigationController (ShouldPopOnBackButton)

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
    
    if([self.viewControllers count] < [navigationBar.items count]) {
        return YES;
    }
    
    BOOL shouldPop = YES;
    UIViewController* vc = [self topViewController];
    if([vc respondsToSelector:@selector(navigationShouldPopOnBackButton)]) {
        shouldPop = [vc navigationShouldPopOnBackButton];
    }
    
    if(shouldPop) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self popViewControllerAnimated:YES];
        });
    } else {
        // 取消 pop 后,復原返回按鈕的狀態
        for(UIView *subview in [navigationBar subviews]) {
            if(0. < subview.alpha && subview.alpha < 1.) {
                [UIView animateWithDuration:.25 animations:^{
                    subview.alpha = 1.;
                }];
            }
        }
    }
    return NO;
}

@end

調用:
在需要定制的ViewController中導入分類

#import "UIViewController+BackButtonHandler.h"

重寫navigationShouldPopOnBackButton方法:

- (void)navigationShouldPopOnBackButton {
    // 定制具體的pop方式
    if ([self.inputParameter[@"isAgreementPage"] boolValue]) {
        [self.navigationController popToRootViewControllerAnimated:YES];
    } else {
        [self.navigationController popViewControllerAnimated:YES];
    }
}

@end

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容