iOS 내 비게 이 션 표시 줄 되 돌리 기 단추 문제 해결 방법
UIBarButtonItem *backBtn = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = backBtn;
또한 루트 컨트롤 러 를 만 들 고 상기 코드 를 사용 한 후에 다른 컨트롤 러 가 이 컨트롤 러 를 계승 하여 대량 작업 을 할 수 있 습 니 다.그러나 되 돌아 갈 클릭 이 벤트 를 사용자 정의 해 야 할 때 위 방법 에 target 과 action 을 추가 하 는 것 은 불가능 합 니 다.이 동시에 문제 가 발생 할 수 있 습 니 다.즉,실제 되 돌아 가기 버튼 의 클릭 영역 은 버튼 이 보 이 는 범위 보다 넓 고 보통 화살표 오른쪽 30 거 리 를 클릭 할 수 있 습 니 다.다음은 제 가 여러분 을 데 리 고 이 문제 들 이 발생 하 는 원인 과 이 문제 들 을 어떻게 더 잘 해결 하 는 지 알 아 보 겠 습 니 다.우선 위 코드 에 따라 되 돌아 오 는 단추 문 자 를 제거 한 후 내 비게 이 션 표시 줄 보기 의 구조 적 차원 을 살 펴 보 겠 습 니 다.내 비게 이 션 표시 줄 의 보기 로드 와 초기 화 는 view Controller 의 view 와 다 르 기 때문에 veiw DidLoad 에서 관찰 할 수 없습니다(view WillAppear 에서 도 안 됩 니 다).view DidLoad 에서 완전한 내 비게 이 션 표시 줄 보기 구조 차원 을 볼 수 있 습 니 다.텍스트 를 지 우 는 리 턴 버튼 컨트롤 러 가 있 는 viewdLoad 에서 정지점 을 찍 고 콘 솔 에서 실행 할 수 있 습 니 다.
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
직접 보기 가 쉽 지 않 을 수도 있 습 니 다.Xcode 의"Debug view Hierarchy"나 Reveal 도 구 를 결합 하여 실제 보기 구 조 를 봐 야 합 니 다.UINavigation Bar 에 4 가지 유형 이 포함 되 어 있 는 것 을 볼 수 있 습 니 다.이들 의 대체적인 역할 은:
_UINavigationBarBackground:(UIImageView)내 비게 이 션 표시 줄 배경 그림(그림 을 직접 설정 할 수 없 음)
UINavigationItemView:(UIView)내 비게 이 션 표시 줄 제목 포함
UINavigation ItemButtonView:(UIView)내 비게 이 션 표시 줄 왼쪽 보기 포함(제거 불가,크기 변경,색상 변경,숨 길 수 있 음,클릭 영역 크기 결정)
_UINavigation BarBackIndicatorView:(UIImageView)내 비게 이 션 표시 줄 되 돌리 기 단추 화살표 그림(그림 수정 불가)
_UINavigation BarBackIndicatorView 는 반환 단추 의 화살표,즉 우리 가 보존 해 야 할 것 이다.UINavigation ItemButtonView 는 우리 가 연구 해 야 할 것 이자 앞에서 언급 한 문제 의 주요 원인 이다.이 대상 이 콘 솔 에서 출력 하 는 것 을 다시 한 번 보 세 요:
| | | <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>>
이 UINavigation ItemButtonView 는 시스템 이 이 view 의 draw 방법 에서 frame 을 결정 하고 frame 을 수정 하면 needdisplay 를 촉발 하여 frame 을 다시 바 꿉 니 다.따라서 이 view 는 그 위의 label(즉,되 돌아 가기 단추 에 표 시 된 텍스트)의 내용 변화 에 따라 너비 만 바 꿉 니 다.우 리 는 label 의 내용 을 비 워 두 었 지만 이 UINavigation ItemButtonView 의 크기 는 바 뀌 지 않 았 고 클릭 영역 도 바 뀌 지 않 았 습 니 다.콘 솔 에서 도 볼 수 있 는 이 veiw 의 userInteractionEnabled 속성 은 NO 입 니 다.이 view 를 클릭 했다 면 현재 이 view 는 상호작용 이 불가능 합 니 다.클릭 이벤트 에 진정 으로 응답 하 는 것 은 이 view 뒤의 특정한 컨트롤(보기 구조 와 코드 에서 이 컨트롤 을 발견 하지 못 했 음)임 을 설명 할 수 있 습 니 다.따라서 제 가 전에 언급 한 문 제 를 해결 하려 면 이 UINavigation ItemButtonView 를 이용 해 야 합 니 다.view Did Appear 에서 UINavigation ItemButtonView 를 찾 을 수 있 습 니 다.(옮 겨 다 니 는 방식 으로 가 져 오 면 지연 이 있 습 니 다.이 view 의 위치 가 세 번 째 로 고정 되 어 있 기 때문에 저희 가 직접 가 져 오 면 됩 니 다)userInteractionEnabled 를 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];
}
이렇게 하면 반환 단추 의 클릭 이 벤트 를 바 꿀 수 있 습 니 다.이 때 클릭 범 위 를 해결 하려 면 이 view 에 지정 한 크기 의 단 추 를 추가 할 수 밖 에 없습니다.마지막 으로 정리 한 해결 방법 은 view Controller 의 분 류 를 만 드 는 것 입 니 다.
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
프로젝트 에 생 성 된 후 유효 합 니 다.모든 viewController 에서 viewDidLoad 를 실행 할 때 되 돌아 오 는 단추 의 텍스트 를 비 워 두 고 viewDidAppear 를 실행 할 때 사용자 정의 단 추 를 추가 하여 pop 이벤트 에 응답 하 는 것 입 니 다.사용자 정의 반환 이벤트 가 필요 하 다 면 저 는.h 에서 반환 이벤트 가 열 립 니 다.해당 하 는 view DidLoad 에서 customeNavBackButton Method 방법 을 복사 하면 되 돌아 가기 단 추 를 눌 렀 을 때 복사 하 는 방법 을 실행 할 수 있 습 니 다.됐 습 니 다.간단 하지 않 습 니까?
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
View의 레이아웃 방법을 AutoLayout에서 따뜻한 손 계산으로 하면 성능이 9.26배로 된 이야기이 기사는 의 15 일째 기사입니다. 어제는 에서 이었습니다. 손 계산을 권하는 의도는 없고, 특수한 상황하에서 계측한 내용입니다 화면 높이의 10 배 정도의 contentView가있는 UIScrollView 레이아...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.