[ios] 내비게이션 컨트롤러에서 뒤로 버튼에 대한 동작 설정

탐색 컨트롤러에서 뒤로 버튼의 기본 동작을 덮어 쓰려고합니다. 타겟 버튼에 타겟에 액션을 제공했습니다. 백 버튼 속성을 통해 할당 할 때 이상한 점은주의를 기울이지 않고 현재보기를 팝업하고 루트로 돌아갑니다.

UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
                                  initWithTitle: @"Servers"
                                  style:UIBarButtonItemStylePlain
                                  target:self
                                  action:@selector(home)];
self.navigationItem.backBarButtonItem = backButton;

내가 통해 설정 자마자 leftBarButtonItemnavigationItem내 조치를 호출하는 대신 화살표가 붙은 다시 하나의 일반 라운드 같은 그러나 다음 버튼 외모 :

self.navigationItem.leftBarButtonItem = backButton;

루트보기로 돌아 가기 전에 사용자 지정 작업을 호출하려면 어떻게해야합니까? 기본 뒤로 동작을 덮어 쓸 수있는 방법이 있습니까, 아니면 뷰를 떠날 때 항상 호출되는 메소드가 viewDidUnload있습니까?



답변

프레스를 감지하려는 뷰 컨트롤러에 이것을 넣으십시오.

-(void) viewWillDisappear:(BOOL)animated {
    if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
       // back button was pressed.  We know this is true because self is no longer
       // in the navigation stack.  
    }
    [super viewWillDisappear:animated];
}


답변

UIViewController-BackButtonHandler 확장을 구현했습니다 . 서브 클래스를 만들 필요가 없으며 프로젝트에 넣고 클래스의 navigationShouldPopOnBackButton메소드를 재정의하십시오 UIViewController.

-(BOOL) navigationShouldPopOnBackButton {
    if(needsShowConfirmation) {
        // Show confirmation alert
        // ...
        return NO; // Ignore 'Back' button this time
    }
    return YES; // Process 'Back' button click and Pop view controler
}

샘플 앱을 다운로드하십시오 .


답변

Amagrammer와 달리 가능합니다. 하위 클래스를 만들어야합니다 navigationController. 나는 여기에 모든 것을 설명했다 (예제 코드 포함).


답변

스위프트 버전 :

( https://stackoverflow.com/a/19132881/826435 )

뷰 컨트롤러에서 프로토콜을 준수하고 필요한 모든 작업을 수행하면됩니다.

extension MyViewController: NavigationControllerBackButtonDelegate {
    func shouldPopOnBackButtonPress() -> Bool {
        performSomeActionOnThePressOfABackButton()
        return false
    }
}

그런 다음 클래스를 만들고 NavigationController+BackButton아래 코드를 복사하여 붙여 넣습니다.

protocol NavigationControllerBackButtonDelegate {
    func shouldPopOnBackButtonPress() -> Bool
}

extension UINavigationController {
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        // Prevents from a synchronization issue of popping too many navigation items
        // and not enough view controllers or viceversa from unusual tapping
        if viewControllers.count < navigationBar.items!.count {
            return true
        }

        // Check if we have a view controller that wants to respond to being popped
        var shouldPop = true
        if let viewController = topViewController as? NavigationControllerBackButtonDelegate {
            shouldPop = viewController.shouldPopOnBackButtonPress()
        }

        if (shouldPop) {
            DispatchQueue.main.async {
                self.popViewController(animated: true)
            }
        } else {
            // Prevent the back button from staying in an disabled state
            for view in navigationBar.subviews {
                if view.alpha < 1.0 {
                    UIView.animate(withDuration: 0.25, animations: {
                        view.alpha = 1.0
                    })
                }
            }

        }

        return false
    }
}


답변

직접 할 수는 없습니다. 몇 가지 대안이 있습니다.

  1. UIBarButtonItem테스트 통과시 탭 및 팝업으로 확인되는 나만의 맞춤 설정 만들기
  2. 키보드 에서 또는 버튼을 누른 후 호출 UITextField되는와 같은 대리자 메소드를 사용하여 양식 필드 컨텐츠의 유효성을 검증하십시오.-textFieldShouldReturn:ReturnDone

첫 번째 옵션의 단점은 사용자 지정 막대 버튼에서 뒤로 버튼의 왼쪽 화살표 스타일에 액세스 할 수 없다는 것입니다. 따라서 이미지를 사용하거나 일반 스타일 버튼으로 이동해야합니다.

두 번째 옵션은 대리자 메서드에서 텍스트 필드를 다시 가져 오기 때문에 유용합니다. 따라서 유효성 검사 논리를 대리자 콜백 메서드로 전송 된 특정 텍스트 필드에 대상으로 지정할 수 있습니다.


답변

몇 가지 스레딩 이유 때문에 @HansPinckaers가 언급 한 솔루션이 나에게 맞지 않았지만 뒤로 버튼을 터치하는 가장 쉬운 방법을 찾았습니다. 다른 사람. 트릭은 정말 쉽습니다. 투명 UIButton을 UINavigationBar의 하위 뷰로 추가하고 선택기를 마치 실제 버튼 인 것처럼 설정하십시오! 다음은 Monotouch와 C #을 사용한 예이지만 objective-c 로의 번역을 찾기가 어렵지 않아야합니다.

public class Test : UIViewController {
    public override void ViewDidLoad() {
        UIButton b = new UIButton(new RectangleF(0, 0, 60, 44)); //width must be adapted to label contained in button
        b.BackgroundColor = UIColor.Clear; //making the background invisible
        b.Title = string.Empty; // and no need to write anything
        b.TouchDown += delegate {
            Console.WriteLine("caught!");
            if (true) // check what you want here
                NavigationController.PopViewControllerAnimated(true); // and then we pop if we want
        };
        NavigationController.NavigationBar.AddSubview(button); // insert the button to the nav bar
    }
}

재미있는 사실 : 테스트 목적으로 가짜 버튼에 적합한 치수를 찾으려면 배경색을 파란색으로 설정하고 뒤로 버튼 뒤에 표시 합니다! 어쨌든 원래 버튼을 대상으로하는 모든 터치를 계속 잡습니다.


답변

이 기술을 사용하면 뷰 컨트롤러의 제목에 영향을 주거나 애니메이션 중에 뒤로 버튼 텍스트가 변경되는 것을 보지 않고 “뒤로”버튼의 텍스트를 변경할 수 있습니다.

이것을 호출 뷰 컨트롤러 의 init 메소드에 추가하십시오 .

UIBarButtonItem *temporaryBarButtonItem = [[UIBarButtonItem alloc] init];
temporaryBarButtonItem.title = @"Back";
self.navigationItem.backBarButtonItem = temporaryBarButtonItem;
[temporaryBarButtonItem release];