iOS攔截導(dǎo)航欄返回按鈕事件的正確方式

當(dāng)我們使用了系統(tǒng)的導(dǎo)航欄時(shí)馁菜,默認(rèn)點(diǎn)擊返回按鈕是 pop 回上一個(gè)界面。但是在有時(shí)候旅急,我們需要在點(diǎn)擊導(dǎo)航欄的返回按鈕時(shí)不一定要 pop 回上一界面些椒,比如一個(gè)視頻播放界面,進(jìn)入橫屏后,默認(rèn)點(diǎn)擊返回按鈕仍然是 pop 返回上一個(gè)界面,但是如果我們想要在橫屏點(diǎn)擊返回按鈕的時(shí)候是返回豎屏模式,而不是 pop 到上一界面瓮增,這該怎么實(shí)現(xiàn)呢?

注意:我們要的不是獲取點(diǎn)擊返回按鈕的時(shí)機(jī)哩俭,而是想要攔截點(diǎn)擊返回按鈕的 pop 操作绷跑,使我們可以進(jìn)行選擇性的 pop,而不是必然的 pop凡资。

下面一步步來解決這個(gè)問題砸捏。

一、自定義返回按鈕

第一種隙赁,自定義導(dǎo)航欄的返回按鈕垦藏,雖然這看起來是一種方式,但是也不能從根本上解決伞访;比如整個(gè)應(yīng)用的返回鍵都是統(tǒng)一的掂骏,這時(shí)候再重寫了某個(gè)界面的返回按鈕感覺就不統(tǒng)一了。而且每有一個(gè)界面有這個(gè)需求都需要重新自定義一個(gè)返回按鈕厚掷,顯得不優(yōu)雅弟灼。

自定義返回按鈕的方法很簡單,如下:

// 自定義返回按鈕
- (void)customBackButton{
    UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [backBtn setTitle:@"返回" forState:UIControlStateNormal];
    [backBtn addTarget:self action:@selector(backBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
    backBtn.frame = CGRectMake(0, 0, 60, 40);
    [backBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    UIBarButtonItem *item = [[UIBarButtonItem alloc]initWithCustomView:backBtn];
    self.navigationItem.leftBarButtonItem = item;
}
// 返回按鈕按下
- (void)backBtnClicked:(UIButton *)sender{
    if (_isLandscape) {
        // 進(jìn)入豎屏
        [self enterPortrait];   
        return;
    }
    // pop
    [self.navigationController popViewControllerAnimated:YES];
}

二蝗肪、為 UINavigationController 添加 category

此方法來自 github:UIViewController-BackButtonHandler

由于系統(tǒng)的 UINavigationController 使用了一個(gè) UINavigationBar 來管理 Controller 的 pop 和 push 等操作袜爪,所以仔細(xì)查看 UINavigationBar 的 API蠕趁,會(huì)發(fā)現(xiàn)一個(gè) UINavigationBarDelegate薛闪,它包含了四個(gè)方法:

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPushItem:(UINavigationItem *)item; // called to push. return NO not to.
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item;    // called at end of animation of push or immediately if not animated
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;  // same as push methods
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item;

我們會(huì)驚喜的第一個(gè)不就是我們想要的效果嗎?因?yàn)樵摲椒ǚ祷?YES 則 pop俺陋,若返回NO豁延,則不POP昙篙。

因此我們可以為 UINavigatonController 創(chuàng)建一個(gè) Category,來定制navigationBar: shouldPopItem: 的邏輯诱咏。這里需要注意的是苔可,我們不需要去設(shè)置 delegate,因?yàn)?UINavigatonController 自帶的 UINavigationBar 的 delegate 就是導(dǎo)航欄本身袋狞。這樣還有個(gè)問題就是焚辅,那在實(shí)際的 Controller 里面怎么控制呢?因此同樣需要對 UIViewController 添加一個(gè) Protocol苟鸯,這樣在 Controller 中使用該 Protocol 提供的方法即可進(jìn)行控制了同蜻,代碼如下:

// UIViewController+BackButtonHandler.h
@protocol BackButtonHandlerProtocol <NSObject>
@optional
// 重寫下面的方法以攔截導(dǎo)航欄返回按鈕點(diǎn)擊事件,返回 YES 則 pop早处,NO 則不 pop
-(BOOL)navigationShouldPopOnBackButton;
@end

@interface UIViewController (BackButtonHandler) <BackButtonHandlerProtocol>

@end
// UIViewController+BackButtonHandler.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 后湾蔓,復(fù)原返回按鈕的狀態(tài)
        for(UIView *subview in [navigationBar subviews]) {
            if(0. < subview.alpha && subview.alpha < 1.) {
                [UIView animateWithDuration:.25 animations:^{
                    subview.alpha = 1.;
                }];
            }
        }
    }
    return NO;
}

到這兒,幾乎就完美的解決一開始的問題了砌梆,使用方法也非常簡單

(1). 在一個(gè) Controller 中:

#import "UIViewController+BackButtonHandler.h"

(2). 重寫 navigationShouldPopOnBackButton 方法

- (BOOL)navigationShouldPopOnBackButton{
    [[[UIAlertView alloc] initWithTitle:@"提示" message:@"確定返回上一界面?"
                               delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil] show];
    return NO;
}
// UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex{
    if (buttonIndex==1) {
        [self.navigationController popViewControllerAnimated:YES];
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末默责,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子咸包,更是在濱河造成了極大的恐慌桃序,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诉儒,死亡現(xiàn)場離奇詭異葡缰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)忱反,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門泛释,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人温算,你說我怎么就攤上這事怜校。” “怎么了注竿?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵茄茁,是天一觀的道長。 經(jīng)常有香客問我巩割,道長裙顽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任宣谈,我火速辦了婚禮愈犹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己漩怎,他們只是感情好勋颖,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勋锤,像睡著了一般饭玲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叁执,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天茄厘,我揣著相機(jī)與錄音,去河邊找鬼谈宛。 笑死蚕断,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的入挣。 我是一名探鬼主播亿乳,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼径筏!你這毒婦竟也來了葛假?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤滋恬,失蹤者是張志新(化名)和其女友劉穎聊训,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恢氯,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡带斑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了勋拟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勋磕。...
    茶點(diǎn)故事閱讀 40,427評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖敢靡,靈堂內(nèi)的尸體忽然破棺而出挂滓,到底是詐尸還是另有隱情,我是刑警寧澤啸胧,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布赶站,位于F島的核電站,受9級特大地震影響纺念,放射性物質(zhì)發(fā)生泄漏贝椿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一陷谱、第九天 我趴在偏房一處隱蔽的房頂上張望烙博。 院中可真熱鬧,春花似錦、人聲如沸习勤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽图毕。三九已至,卻和暖如春眷唉,著一層夾襖步出監(jiān)牢的瞬間予颤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工冬阳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蛤虐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓肝陪,卻偏偏與公主長得像驳庭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子氯窍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫饲常、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,117評論 4 61
  • 天寒地凍時(shí)狼讨,角落里的陽光彌足珍貴贝淤。 最近的生活總是不盡如人意,仿佛整天有一大片烏云籠罩心頭政供。我狂奔著想擺脫掉但難過...
    邱紋閱讀 438評論 1 2
  • 年底都很忙播聪。喜歡忙碌的感覺,充實(shí)布隔。生活就是不斷的問題疊加离陶,然后不斷的去解決⌒铺矗總想著一帆風(fēng)順是不可能的枕磁。有時(shí)加班回家...
    一生為一人HT閱讀 201評論 1 0
  • 江城子 元旦 春城之夜披彩虹, 笑語聲术吝,飄到空计济, 車滿街頭,節(jié)日氣氛濃排苍。 努力方修幸福路沦寂, 肯拼搏,事終成淘衙。 雞來...
    春韻留芳閱讀 116評論 0 0
  • Web應(yīng)用被應(yīng)用開發(fā)者創(chuàng)建传藏,這些開發(fā)者給予、賣應(yīng)用,或者為了安裝到一個(gè)運(yùn)行時(shí)環(huán)境毯侦,把應(yīng)用轉(zhuǎn)移應(yīng)用到一個(gè)部署者哭靖。應(yīng)用...
    Lucky_Micky閱讀 2,552評論 0 1