ViewWillDisAppear : View Controller가 팝업 중인지 또는 하위 뷰 컨트롤러가 표시되는지 확인

StackOverflow https://stackoverflow.com/questions/1816614

문제

이 문제에 대한 좋은 해결책을 찾기 위해 고군분투하고 있습니다. 보기 컨트롤러에서 -viewWillDisappear: 방법, 뷰 컨트롤러가 탐색 컨트롤러 스택으로 밀려 나가는 지 또는 뷰 컨트롤러가 튀어 나와서 사라 졌기 때문에 있는지 여부를 결정하는 방법을 찾아야합니다.

현재 나는 다음과 같은 깃발을 설정합니다 isShowingChildViewController 그러나 그것은 상당히 복잡해지고 있습니다. 내가 그것을 감지 할 수 있다고 생각하는 유일한 방법은 -dealloc 방법.

도움이 되었습니까?

해결책

다음을 사용할 수 있습니다.

- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  NSArray *viewControllers = self.navigationController.viewControllers;
  if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
    // View is disappearing because a new view controller was pushed onto the stack
    NSLog(@"New view controller was pushed");
  } else if ([viewControllers indexOfObject:self] == NSNotFound) {
    // View is disappearing because it was popped from the stack
    NSLog(@"View controller was popped");
  }
}

물론 UinavigationController의 View Controller 스택 (ViewControllers 속성을 통해 노출)이 ViewWillDisAppear가 호출되는 시점에 의해 업데이트 되었기 때문에 이것은 가능합니다.

다른 팁

가장 쉬운 방법은 다음과 같습니다.

 - (void)viewWillDisappear:(BOOL)animated
{
    if ([self isMovingFromParentViewController])
    {
        NSLog(@"View controller was popped");
    }
    else
    {
        NSLog(@"New view controller was pushed");
    }
    [super viewWillDisappear:animated];
}

빠른:

override func viewWillDisappear(animated: Bool)
{
    if isMovingFromParentViewController
    {
        print("View controller was popped")
    }
    else
    {
        print("New view controller was pushed")
    }
    super.viewWillDisappear(animated)
}

UIViewController.h의 Apple 문서에서 :

"이 네 가지 방법은 뷰 컨트롤러의 외관 콜백에서 사용하여 자식 뷰 컨트롤러로 제시, 해고 또는 추가 또는 제거되는지 확인할 수 있습니다. 예를 들어, 뷰 컨트롤러는 해산되었거나 사라 졌는지 확인할 수 있습니다. ViewWillDisAppear : 표현을 확인하여 메소드 ([Self IsbeingDismised] || [Self IsMovingFromperentViewController])

- (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0);

- (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0);

- (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0);

- (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0);

그렇습니다.이를 수행하는 유일한 방법은 다음과 같은 방법입니다.

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if ([self isBeingDismissed] || [self isMovingFromParentViewController]) {
    }
}

스위프트 3 버전 :

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    if self.isBeingDismissed || self.isMovingFromParentViewController { 
    }
}

당신의 견해가 튀어 나오는지 알고 싶다면 방금 발견했습니다. self.navigationController ~이다 nil 안에 viewDidDisappear, 컨트롤러 스택에서 제거 될 때. 그래서 그것은 간단한 대안 테스트입니다.

(이것은 모든 종류의 다른 연소를 시도한 후 발견합니다. 팝에 통보 할 뷰 컨트롤러를 등록 할 내비게이션 컨트롤러 프로토콜이 없다는 것에 놀랐습니다. 사용할 수 없습니다. UINavigationControllerDelegate 그것은 실제로 실제 디스플레이 작업을 수행하기 때문입니다.)

스위프트 4

override func viewWillDisappear(_ animated: Bool)
    {
        super.viewWillDisappear(animated)
        if self.isMovingFromParent
        {
            //View Controller Popped
        }
        else
        {
            //New view controller pushed
        }
    }

Swift에서 :

 override func viewWillDisappear(animated: Bool) {
    if let navigationController = self.navigationController {
        if !contains(navigationController.viewControllers as! Array<UIViewController>, self) {
        }
    }

    super.viewWillDisappear(animated)

}

이것에 대한 Apple의 문서는 이해하기 어렵다는 것을 알았습니다. 이 확장은 각 내비게이션에서 상태를 보는 데 도움이됩니다.

extension UIViewController {
    public func printTransitionStates() {
        print("isBeingPresented=\(isBeingPresented)")
        print("isBeingDismissed=\(isBeingDismissed)")
        print("isMovingToParentViewController=\(isMovingToParentViewController)")
        print("isMovingFromParentViewController=\(isMovingFromParentViewController)")
    }
}

이 질문은 상당히 오래되었지만 우연히 보았으므로 모범 사례를 게시하고 싶습니다 (AFAIK)

당신은 그냥 할 수 있습니다

if([self.navigationController.viewControllers indexOfObject:self]==NSNotFound)
 // view controller popped
}

이것은 다음에 적용됩니다 IOS 7, 그것이 다른 사람에게 적용되는지 모르겠습니다. 내가 아는 바에서 viewDidDisappear 보기가 이미 튀어 나왔습니다. 쿼리 할 때입니다 self.navigationController.viewControllers 당신은 얻을 것입니다 nil. 그러니 그게 nil인지 확인하십시오.

tl; dr

 - (void)viewDidDisappear:(BOOL)animated
 {
    [super viewDidDisappear:animated];
    if (self.navigationController.viewControllers == nil) {
        // It has been popped!
        NSLog(@"Popped and Gone");
    }
 }

SEGUE는 iOS 6+ 에서이 문제를 처리하는 매우 효과적인 방법이 될 수 있습니다. 인터페이스 빌더에 특정 SEGUE 식별자를 제공 한 경우 확인할 수 있습니다. prepareForSegue.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"LoginSegue"]) {
       NSLog(@"Push");
       // Do something specific here, or set a BOOL indicating
       // a push has occurred that will be checked later
    }
}

나는 당신이 스택에 밀어 넣을 때 새로운보기를 밀어 내비게이션 컨트롤러의 스택 아래로 내려 가고 있다고 생각합니다. 나는 사용하는 것이 좋습니다 viewDidUnload 추가하는 방법 NSLog 무슨 일이 일어나고 있는지 알 수 있도록 콘솔에 무언가를 쓰려는 문장을 추가하고 싶을 수도 있습니다. NSLog 에게 viewWillDissappeer.

다음은 Sbrocket의 답변과 동일한 것을 달성하는 카테고리입니다.

헤더:

#import <UIKit/UIKit.h>

@interface UIViewController (isBeingPopped)

- (BOOL) isBeingPopped;

@end

원천:

#import "UIViewController+isBeingPopped.h"

@implementation UIViewController (isBeingPopped)

- (BOOL) isBeingPopped {
    NSArray *viewControllers = self.navigationController.viewControllers;
    if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
        return NO;
    } else if ([viewControllers indexOfObject:self] == NSNotFound) {
        return YES;
    }
    return NO;
}

@end
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top