欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于iOS導(dǎo)航欄返回按鈕問題的解決方法

 更新時間:2020年05月26日 14:56:01   作者:千葉的博客  
這篇文章主要為大家詳細(xì)介紹了關(guān)于iOS導(dǎo)航欄返回按鈕問題的解決方法,對iOS自定義backBarButtonItem的點(diǎn)擊事件進(jìn)行介紹,感興趣的小伙伴們可以參考一下

最近遇到一個關(guān)于導(dǎo)航欄返回按鈕的問題,因?yàn)橹绊?xiàng)目里面都是用的系統(tǒng)默認(rèn)的返回按鈕樣式所以沒有想過要去更改,后來有需要將返回按鈕箭頭旁邊的文字去掉,同時將該返回按鈕的點(diǎn)擊事件重新定義。一開始嘗試自定義按鈕然后設(shè)置為leftBarButtonItem,但是這樣圖片可能跟系統(tǒng)自帶的不一樣,還有就是返回按鈕的位置跟系統(tǒng)自帶的不一樣。后來找了一些資料,發(fā)現(xiàn)將文字去掉比較簡單,一般做法是控制器中添加如下代碼,然后他的下一級控制就有一個只有箭頭沒有文字返回按鈕:

復(fù)制代碼 代碼如下:
UIBarButtonItem *backBtn = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = backBtn;

也可以創(chuàng)建一個根控制器在其中使用上述代碼然后讓其他控制器繼承這個根控制器實(shí)現(xiàn)批量操作。但是如果遇到需要自定義該返回的點(diǎn)擊事件的時候,在上面方法中添加target與action是不可行的,同時這種做法也會產(chǎn)生一個問題,就是實(shí)際的返回按鈕點(diǎn)擊區(qū)域總是比按鈕看到的范圍大,一般是距離箭頭右邊30距離都可點(diǎn)擊。接下來我就帶大家一起了解這些問題產(chǎn)生的原因以及如何更好的解決這些問題。

首先我們看一下按照上面代碼去掉返回按鈕文字之后的導(dǎo)航欄視圖的結(jié)構(gòu)層次,因?yàn)閷?dǎo)航欄的視圖加載以及初始化跟viewController的view不一樣,不能再veiwDidLoad中去觀察(viewWillAppear中也不行)要在viewDidLoad中才可以看到完整的導(dǎo)航欄視圖結(jié)構(gòu)層次。我們可以在一個有去掉文字的返回按鈕控制器的viewDidLoad中打上斷點(diǎn)然后在控制臺執(zhí)行:

po [[UIWindow keyWindow] recursiveDescription]

會得到如下輸出:

<UIWindow: 0x8d6f970; frame = (0 0; 320 480); autoresize = W+H; gestureRecognizers = <NSArray: 0x8d5dbf0>; layer = <UIWindowLayer: 0x8d717d0>>
 | <UILayoutContainerView: 0x8d7bbf0; frame = (0 0; 320 480); autoresize = W+H; gestureRecognizers = <NSArray: 0x8d78a70>; layer = <CALayer: 0x8d7bcd0>>
 | | <UINavigationTransitionView: 0x8d813f0; frame = (0 0; 320 480); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x8d814d0>>
 | | | <UIViewControllerWrapperView: 0x8d61050; frame = (0 0; 320 480); autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x8d88f40>>
 | | | | <UIView: 0x8ab0dc0; frame = (0 0; 320 480); autoresize = RM+BM; layer = <CALayer: 0x8ab0610>>
 | | | | | <_UILayoutGuide: 0x8ab0e20; frame = (0 0; 0 64); hidden = YES; layer = <CALayer: 0x8ab0e90>>
 | | | | | <_UILayoutGuide: 0x8ab1080; frame = (0 480; 0 0); hidden = YES; layer = <CALayer: 0x8ab10f0>>
 | | <UINavigationBar: 0x8d75c40; frame = (0 20; 320 44); opaque = NO; autoresize = W; userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0x8d5e750>; layer = <CALayer: 0x8d70f00>>
 | | | <_UINavigationBarBackground: 0x8d59af0; frame = (0 -20; 320 64); opaque = NO; autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x8d549f0>> - (null)
 | | | | <_UIBackdropView: 0x8d7c440; frame = (0 0; 320 64); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <_UIBackdropViewLayer: 0x8d7e7b0>>
 | | | | | <_UIBackdropEffectView: 0x8d7f1c0; frame = (0 0; 320 64); clipsToBounds = YES; opaque = NO; autoresize = W+H; userInteractionEnabled = NO; animations = { filters.colorMatrix.inputColorMatrix=<CABasicAnimation: 0x8ba4490>; }; layer = <CABackdropLayer: 0x8d7f480>>
 | | | | | <UIView: 0x8d7fc80; frame = (0 0; 320 64); hidden = YES; opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x8d7fce0>>
 | | | | <UIImageView: 0x8d67cc0; frame = (0 64; 320 0.5); userInteractionEnabled = NO; layer = <CALayer: 0x8d67d50>> - (null)
 | | | <UINavigationItemView: 0x8ab6400; frame = (124 8; 163 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ab6480>>
 | | | | <UILabel: 0x8ab64b0; frame = (0 3; 163 22); text = 'A Story About a Fish'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ab6550>>
 | | | <UINavigationItemButtonView: 0x8ab6c80; frame = (8 6; 41 30); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ab6d60>>
 | | | | <UILabel: 0x8ab6f10; frame = (-981 -995; 91 22); text = ''; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ab6fb0>>
 | | | <_UINavigationBarBackIndicatorView: 0x8d87560; frame = (8 12; 12.5 20.5); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8d87650>> - Back

直接看或許不容易懂,還需要結(jié)合Xcode的“Debug view Hierarchy”或者是Reveal工具看實(shí)際視圖結(jié)構(gòu):

我們可以看到在UINavigationBar中包含有4個類,它們大致的作用是:

_UINavigationBarBackground :(UIImageView)導(dǎo)航欄背景圖(不可以直接設(shè)置圖片)
UINavigationItemView :(UIView)包含顯示導(dǎo)航欄標(biāo)題
UINavigationItemButtonView :(UIView)包含顯示導(dǎo)航欄左視圖(不可移除,更改大小,顏色,可以隱藏,決定了點(diǎn)擊區(qū)域的大?。?br /> _UINavigationBarBackIndicatorView :(UIImageView)導(dǎo)航欄返回按鈕箭頭圖片(不可以修改圖片)
_UINavigationBarBackIndicatorView就是返回按鈕的箭頭也就是我們需要保留的,UINavigationItemButtonView就是我們需要研究的也是我們前面提到問題的主要原因所在。再次看看這個對象在控制臺的輸出:

 | | | <UINavigationItemButtonView: 0x8ab6c80; frame = (8 6; 41 30); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ab6d60>>
 | | | | <UILabel: 0x8ab6f10; frame = (-981 -995; 91 22); text = ''; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ab6fb0>>

這個UINavigationItemButtonView應(yīng)該是系統(tǒng)在這個view的draw方法里就決定frame,修改frame就觸發(fā)needdisplay重新改變它的frame,因此這個view只會根據(jù)其上的label(也就是返回按鈕顯示的文字)的內(nèi)容變化而改變寬度其余基本不可變,我們雖然將label的內(nèi)容設(shè)置為空但是這個UINavigationItemButtonView的大小卻并沒有改變同時點(diǎn)擊區(qū)域也沒有改變。從控制臺里的還可看到這個veiw的userInteractionEnabled屬性為NO,如果說點(diǎn)擊的是這個view,但現(xiàn)在這個view是不可交互的,只能說明是真正響應(yīng)點(diǎn)擊事件的是這個view背后的某個控件(視圖結(jié)構(gòu)和代碼里都沒有發(fā)現(xiàn)這個控件)。因此要想解決我之前提到的問題就得利用這個UINavigationItemButtonView,我們可以在viewDidAppear中取得到UINavigationItemButtonView(如果用遍歷的方式獲取會有一個延遲,因?yàn)檫@個view的位置固定為第三個所以我們就直接獲取就可以了),將其userInteractionEnabled設(shè)置為yes并且在這個View上添加手勢tap事件即可:

UIView *nav_back = [self.navigationController.navigationBar.subviews objectAtIndex:2];
if ([nav_back isKindOfClass:NSClassFromString(@"UINavigationItemButtonView")]) {
 nav_back.userInteractionEnabled = YES;
 // UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(backAction:)];
 // [nav_back addGestureRecognizer:tap];
 UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
 backButton.frame = CGRectMake(0, 0, 20, 21);
 [backButton addTarget:self action:@selector(customMethod) forControlEvents:UIControlEventTouchUpInside];
 [nav_back addSubview:backButton];
 }

這樣可以改變返回按鈕的點(diǎn)擊事件,此時想要解決點(diǎn)擊范圍只能在這個view上添加一個指定大小的按鈕了。最后總結(jié)出來的解決辦法就是創(chuàng)建一個viewController的分類:

UIViewController+CustomBackButton.h文件

#import <UIKit/UIKit.h>

@interface UIViewController (CustomBackButton)

- (void)customNavBackButtonMethod;

@end

UIViewController+CustomBackButton.m文件

#import "UIViewController+CustomBackButton.h"
#import <objc/runtime.h>

@implementation UIViewController (CustomBackButton)

+ (void)load {
 static dispatch_once_t onceToken;
 dispatch_once(&onceToken, ^{
 Class class = [self class];
 
 SEL originalSelector = @selector(viewDidLoad);
 SEL swizzledSelector = @selector(mm_viewDidLoad);
 
 SEL originalSelector1 = @selector(viewDidAppear:);
 SEL swizzledSelector1 = @selector(mm_viewDidAppear);
 
 Method originalMethod = class_getInstanceMethod(class, originalSelector);
 Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
 
 Method originalMethod1 = class_getInstanceMethod(class, originalSelector1);
 Method swizzledMethod1 = class_getInstanceMethod(class, swizzledSelector1);
 
 BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
 BOOL didAddMethod1 = class_addMethod(class, originalSelector1, method_getImplementation(swizzledMethod1), method_getTypeEncoding(swizzledMethod1));

 if (didAddMethod) {
 class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
 } else {
 method_exchangeImplementations(originalMethod, swizzledMethod);
 }
 
 if (didAddMethod1) {
 class_replaceMethod(class, swizzledSelector1, method_getImplementation(originalMethod1), method_getTypeEncoding(originalMethod1));
 } else {
 method_exchangeImplementations(originalMethod1, swizzledMethod1);
 }
 });
}

#pragma mark - Method Swizzling

- (void)mm_viewDidLoad {
 [self mm_viewDidLoad];
 UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
 [self.navigationItem setBackBarButtonItem:backButtonItem];
}

- (void)mm_viewDidAppear {
 [self mm_viewDidAppear];
 UIView *nav_back = [self.navigationController.navigationBar.subviews objectAtIndex:2];
 if ([nav_back isKindOfClass:NSClassFromString(@"UINavigationItemButtonView")]) {
 nav_back.userInteractionEnabled = YES;
 // UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(backAction:)];
 // [nav_back addGestureRecognizer:tap];
 UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
 backButton.frame = CGRectMake(0, 0, 20, 21);
 [backButton addTarget:self action:@selector(customNavBackButtonMethod) forControlEvents:UIControlEventTouchUpInside];
 [nav_back addSubview:backButton];
 }
}


- (void)customNavBackButtonMethod {
 [self.navigationController popViewControllerAnimated:YES];
}

@end

在項(xiàng)目里面創(chuàng)建完以后就會生效。這里所做的就是在所有的viewController執(zhí)行viewDidLoad的時候?qū)⒎祷匕粹o的文字置空,在執(zhí)行viewDidAppear的時候添加一個自定義的按鈕去響應(yīng)pop事件。如果遇到需要自定義返回事件我在.h將返回事件開放出來,只要在對應(yīng)的viewDidLoad中復(fù)寫customNavBackButtonMethod方法就可以在點(diǎn)擊返回按鈕時執(zhí)行到你復(fù)寫的方法中了,好了,是不是感覺很簡單呢。

相關(guān)文章

  • iOS彈幕開發(fā)中遇到的問題匯總

    iOS彈幕開發(fā)中遇到的問題匯總

    最近做項(xiàng)目的時候需要實(shí)現(xiàn)彈幕這個功能, 雖然感覺實(shí)現(xiàn)起來也不是很復(fù)雜,但還是遇到了一些問題,下面這篇文章主要給大家總結(jié)介紹了在iOS彈幕開發(fā)中遇到的問題,文中將解決的方法介紹的非常詳細(xì),需要的朋友可以參考下。
    2018-01-01
  • iOS 指紋解鎖驗(yàn)證TouchID功能

    iOS 指紋解鎖驗(yàn)證TouchID功能

    這篇文章主要介紹了iOS 指紋解鎖驗(yàn)證TouchID功能,非常不錯,具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-03-03
  • Xcode清理緩存和垃圾文件的教程

    Xcode清理緩存和垃圾文件的教程

    下面小編就為大家分享一篇Xcode清理緩存和垃圾文件的教程,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • iOS開發(fā)-調(diào)用系統(tǒng)相機(jī)和相冊獲取照片示例

    iOS開發(fā)-調(diào)用系統(tǒng)相機(jī)和相冊獲取照片示例

    這篇文章主要介紹了iOS開發(fā)-調(diào)用系統(tǒng)相機(jī)和相冊獲取照片示例的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • iOS中只讓textField使用鍵盤通知的實(shí)例代碼

    iOS中只讓textField使用鍵盤通知的實(shí)例代碼

    本文通過實(shí)例代碼給大家介紹了OS中只讓textField使用鍵盤通知的操作方法,代碼簡單易懂,非常不錯,具有參考借鑒加載,需要的的朋友參考下吧
    2017-07-07
  • IOS 實(shí)現(xiàn)搖一搖的操作

    IOS 實(shí)現(xiàn)搖一搖的操作

    這篇文章主要介紹了IOS 實(shí)現(xiàn)搖一搖的操作的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • 百度地圖PC端判斷用戶是否在配送范圍內(nèi)

    百度地圖PC端判斷用戶是否在配送范圍內(nèi)

    在pc端設(shè)置商家的配送范圍,用戶在下單時,根據(jù)用戶設(shè)置的配送地點(diǎn)判斷是否在可配送范圍內(nèi),并給用戶相應(yīng)的提示,下面通過本文給大家分享具有實(shí)現(xiàn)代碼,感興趣的朋友一起學(xué)習(xí)吧
    2016-01-01
  • 分享一些iOS開發(fā)實(shí)用的小技巧

    分享一些iOS開發(fā)實(shí)用的小技巧

    這篇文章主要給大家分享了一些iOS開發(fā)實(shí)用的小技巧,這些小技巧在大家開發(fā)iOS的時候還是相當(dāng)實(shí)用,有需要的朋友們下面來一起看看吧。
    2016-09-09
  • iOS實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時

    iOS實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時

    這篇文章主要介紹了iOS實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時功能,一種方法是利用NSTimer計(jì)時器,另一種方法是利用GCD實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • 微信JSSDK多圖片上傳并且解決IOS系統(tǒng)上傳一直加載的問題

    微信JSSDK多圖片上傳并且解決IOS系統(tǒng)上傳一直加載的問題

    這篇文章主要介紹了微信JSSDK多圖片上傳并且解決IOS系統(tǒng)上傳一直加載的問題的相關(guān)資料,需要的朋友可以參考下
    2016-03-03

最新評論