뷰 컨트롤러가 모달로 표시되는지 또는 탐색 스택에 푸시되는지 확인하는 방법은 무엇입니까?


126

내 뷰 컨트롤러 코드에서 다음을 어떻게 구분할 수 있습니까?

  • 모달로 제시
  • 탐색 스택에 푸시 됨

둘 다 presentingViewController하고 isMovingToParentViewController있습니다 YES그래서 매우 도움이되지 않습니다, 두 경우 모두에서.

복잡한 것은 내 부모 뷰 컨트롤러가 때때로 모달이라는 것입니다.

그것은 내 문제는 내가 내를 포함한다는 것이다 밝혀 HtmlViewControllerA의 UINavigationController다음되게된다. 그래서 내 자신의 시도와 아래의 좋은 답변이 효과가 없었습니다.

HtmlViewController*     termsViewController = [[HtmlViewController alloc] initWithDictionary:dictionary];
UINavigationController* modalViewController;

modalViewController = [[UINavigationController alloc] initWithRootViewController:termsViewController];
modalViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:modalViewController
                   animated:YES
                 completion:nil];

결정하려고하는 대신 모달 일 때 뷰 컨트롤러에 알려주는 것이 좋습니다.

답변:


125

테스트하지 않고 소금 한 알로 섭취하십시오.

- (BOOL)isModal {
     if([self presentingViewController])
         return YES;
     if([[[self navigationController] presentingViewController] presentedViewController] == [self navigationController])
         return YES;
     if([[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]])
         return YES;

    return NO;
 }

12
나는 이것을 다른 SO 게시물에서 발견했습니다. 그러나 푸시 된 뷰 컨트롤러의 부모가 모달이면 작동하지 않습니다. 제가 겪고있는 상황입니다.
의미-문제

2
내가 쓴 것처럼 presentingViewController항상 YES내 경우에 있습니다. 도움이되지 않습니다.
의미-문제

3
presentingViewController루트로 설정된 YES경우 푸시 된 VC에 대해 반환 됩니다 UITabBarController. 그래서 제 경우에는 적합하지 않습니다.
Yevhen Dubinin 2014-06-11

5
뷰 컨트롤러를 제시 한 다음 다른 컨트롤러를 푸시하면 작동하지 않습니다.
Lee

3
"뷰 컨트롤러를 제시하면 작동하지 않고 다른 컨트롤러를 푸시합니다."이것은 의도가 아닙니다. 푸시 된 뷰 컨트롤러가 표시되지 않습니다.
Colin Swelin

87

에서 스위프트 :

클래스 유형별 모달인지 테스트 할 플래그를 추가합니다.

// MARK: - UIViewController implementation

extension UIViewController {

    var isModal: Bool {

        let presentingIsModal = presentingViewController != nil
        let presentingIsNavigation = navigationController?.presentingViewController?.presentedViewController == navigationController
        let presentingIsTabBar = tabBarController?.presentingViewController is UITabBarController

        return presentingIsModal || presentingIsNavigation || presentingIsTabBar
    }
}

4
처럼 VAR에 더 나은해야var isModal: Bool {}
말리 노이즈

1
@malinois이 변경됩니다
YannSteph

명령문 의 마지막 false매개 변수는 무엇을 return합니까?
damjandd

presentingIsNavigation = navigationController? .presentingViewController? .presentedViewController == navigationController && navigationController! = nil
famfamfam

78

한 가지 방법을 간과했습니다 : isBeingPresented.

isBeingPresented 뷰 컨트롤러가 표시되면 true이고 푸시되면 false입니다.

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if ([self isBeingPresented]) {
        // being presented
    } else if ([self isMovingToParentViewController]) {
        // being pushed
    } else {
        // simply showing again because another VC was dismissed
    }
}

2
내가 너무 게시하기 전에 이것을 시도하고 일을하지 않는 isBeingPresented것입니다 NO. 하지만 이제 그 이유를 알았습니다. 제시된 뷰 컨트롤러를 .NET에 내장 UINavigationController하고 있으며 이것이 제가 추진하고있는 것입니다.
의미-문제

1
내비게이션 컨트롤러를 누를 수 없습니다. 아마도 당신은 내비게이션 컨트롤러를 제시하고 있다는 것을 의미했을 것입니다.
rmaddy

3
@jowie 사용 p하지 po원시 값을 인쇄 할 때. po개체를 인쇄하기위한 것입니다.
rmaddy

37
문서 isBeingPresented-이 메서드는 viewWillAppear : 및 viewDidAppear : 메서드 내부에서 호출 될 때만 YES를 반환합니다.
funct7 2015-06-25

4
@Terrence 최신 문서에는 해당 정보가 표시되지 않지만 예전에는 거기에 있었던 것 같습니다. 는 isBeingPresented, isBeingDismissed, isMovingFromParentViewControllerisMovingToParentViewController4 개 내부에만 유효 view[Will|Did][Disa|A]ppear방법.
rmaddy

29

Swift 5
다음은 푸시 된 경우 isModal()반환 이 제시된 스택 에 있을 때 이전 답변에서 언급 된 문제를 해결하는 솔루션입니다 .trueUIViewControllerUINavigationController

extension UIViewController {
    var isModal: Bool {
        if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 {
            return false
        } else if presentingViewController != nil {
            return true
        } else if navigationController?.presentingViewController?.presentedViewController == navigationController {
            return true
        } else if tabBarController?.presentingViewController is UITabBarController {
            return true
        } else {
            return false
        }
    }
}

지금까지 나를 위해 작동합니다. 일부 최적화가 있으면 공유하십시오.


왜 확인해야 tabBarController?.presentingViewController is UITabBarController 합니까? 그것이 presentingViewController또한 UITabBarController 인 경우 중요합니까 ?
Hlung

navigationController가 nil이면 isModal을 반환 true합니다. 이것은 의도 된 것입니까?
Hlung

28

self.navigationController! = nil은 탐색 스택에 있음을 의미합니다.

탐색 컨트롤러가 모달로 표시되는 동안 현재 뷰 컨트롤러가 푸시되는 경우를 처리하기 위해 현재 뷰 컨트롤러가 탐색 스택의 루트 컨트롤러인지 확인하는 몇 줄의 코드를 추가했습니다.

extension UIViewController {
    var isModal: Bool {
        if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 {
            return false
        } else if presentingViewController != nil {
            return true
        } else if let navigationController = navigationController, navigationController.presentingViewController?.presentedViewController == navigationController {
            return true
        } else if let tabBarController = tabBarController, tabBarController.presentingViewController is UITabBarController {
            return true
        } else {
            return false
        }
    }
}

일반적으로 모달로 표시 할 때 viewController를 navigationController에 놓고 표시합니다. 이 경우 귀하의 진술이 잘못되었을 수 있지만 코드에서는이 경우가 처리됩니다. 답변을 개선해주세요 :)
E-Riddie

모든 사용 사례를 처리하는 좋은 작업입니다. 아마도 약간의 리팩토링을위한 공간이지만 여전히 찬성 !!
Jean Raymond Daher

12

스위프트 4

var isModal: Bool {
    return presentingViewController != nil ||
           navigationController?.presentingViewController?.presentedViewController === navigationController ||
           tabBarController?.presentingViewController is UITabBarController
}

Swift 4.2 / iOS 12. 여전히 잘 작동하지만 navigationController? .presentingViewController? .presentedViewController === navigationController는 둘 다 nil 인 경우 true로 평가됩니다 (예 : 아직 실행되지 않은보기 컨트롤러에서 호출하는 경우). 제시).
Eli Burke

7

Swift 5. 깨끗하고 간단합니다.

if navigationController.presentingViewController != nil {
    // Navigation controller is being presented modally
}

1
이것은 나를 위해 트릭을했다
Radu Ursache

3

여기에있는 많은 사람들이 "확인"방법이 모든 경우에 잘 작동하지 않는다고 제안했듯이, 내 프로젝트에서 수동으로 관리 할 수있는 솔루션을 찾았습니다. 요점은 일반적으로 우리가 직접 프레젠테이션을 관리한다는 것입니다. 이것은이면에서 일어나는 일이 아니므로 우리는 성찰해야합니다.

DEViewController.h 파일:

#import <UIKit/UIKit.h>

// it is a base class for all view controllers within a project
@interface DEViewController : UIViewController 

// specify a way viewcontroller, is presented  by another viewcontroller
// the presented view controller should manually assign the value to it
typedef NS_ENUM(NSUInteger, SSViewControllerPresentationMethod) {
    SSViewControllerPresentationMethodUnspecified = 0,
    SSViewControllerPresentationMethodPush,
    SSViewControllerPresentationMethodModal,
};
@property (nonatomic) SSViewControllerPresentationMethod viewControllerPresentationMethod;

// other properties/methods...
@end

이제 프레젠테이션을 다음과 같이 관리 할 수 ​​있습니다.

탐색 스택에 푸시 :

// DETestViewController inherits from DEViewController
DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodPush;
[self.navigationController pushViewController:vc animated:YES];

탐색과 함께 모달로 표시 :

DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodModal;
UINavigationController *nav = [[UINavigationController alloc]
                               initWithRootViewController:vc];
[self presentViewController:nav animated:YES completion:nil];

모달로 제시 :

DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodModal;
[self presentViewController:vc animated:YES completion:nil];

또한 DEViewController앞서 언급 한 속성이 SSViewControllerPresentationMethodUnspecified다음과 같으면 "checking"에 폴백을 추가 할 수 있습니다 .

- (BOOL)isViewControllerPushed
{
    if (self.viewControllerPresentationMethod != SSViewControllerPresentationMethodUnspecified) {
        return (BOOL)(self.viewControllerPresentationMethod == SSViewControllerPresentationMethodPush);
    }

    else {
        // fallback to default determination method
        return (BOOL)self.navigationController.viewControllers.count > 1;
    }
}

3

모달로 표시하는 모든 viewController가 새 navigationController 안에 래핑되었다고 가정하면 (항상 수행해야하는)이 속성을 VC에 추가 할 수 있습니다.

private var wasPushed: Bool {
    guard let vc = navigationController?.viewControllers.first where vc == self else {
        return true
    }

    return false
}

1
어쨌든 항상해야하는 -이유를 설명해주세요.
Alexander Abakumov 2011

알렉산더, 그렇게하면 안 돼요.
nickdnk

2

컨트롤러가 밀려나거나 원하는 곳에서 아래 코드를 사용하지 않는 것을 감지하려면 :

if ([[[self.parentViewController childViewControllers] firstObject] isKindOfClass:[self class]]) {

    // Not pushed
}
else {

    // Pushed
}

이 코드가 누구에게나 도움이되기를 바랍니다.


1
이 메서드는 여러 위치에서 동일한 뷰 컨트롤러 클래스를 사용하는 경우 해당 클래스 만 확인하므로 작동하지 않습니다. 대신 명시 적으로 동등성을 확인할 수 있습니다.
gklka

1

self.navigationController != nil 탐색 스택에 있음을 의미합니다.


25
여전히 모달 탐색 컨트롤러에있을 수 있음
ColdLogic 2014 년

따라서 '모달'과 '탐색 스택에 푸시 됨'은 상호 배타적이지 않습니다. 이것이 컨텍스트에 따라 다르지만 self.navigationController가 nil이 아닌지 확인하면 탐색 컨트롤러의 뷰 컨트롤러인지 여부에 대한 대답이됩니다.
Daniel

@Daniel 차이점은 "푸시 됨"과 "제시됨"입니다. "Modal"은 그것과 아무 관련이 없습니다. "ColdLogic"이 "모달"이라고 말했을 때 "제시"를 의미한다고 믿습니다.
rmaddy

1
if let navigationController = self.navigationController, navigationController.isBeingPresented {
    // being presented
}else{
    // being pushed
}

0

iOS 5.0 이상을 사용하는 경우이 코드를 사용하십시오.

-(BOOL)isPresented
{
    if ([self isBeingPresented]) {
        // being presented
         return YES;
    } else if ([self isMovingToParentViewController]) {
        // being pushed
         return NO;
    } else {
        // simply showing again because another VC was dismissed
         return NO;
    }
}

0

Swift 5
이 편리한 확장 기능은 이전 답변보다 적은 경우를 처리합니다. 이러한 경우는 VC (view controller)가 앱 창의 루트 VC이고 VC는 부모 VC에 자식으로 추가됩니다. viewcontroller가 모달로 표시되는 경우에만 true를 반환하려고합니다.

extension UIViewController {
    /**
      returns true only if the viewcontroller is presented.
    */
    var isModal: Bool {
        if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 {
            return false
        } else if presentingViewController != nil {
            if let parent = parent, !(parent is UINavigationController || parent is UITabBarController) {
                return false
            }
            return true
        } else if let navController = navigationController, navController.presentingViewController?.presentedViewController == navController {
            return true
        } else if tabBarController?.presentingViewController is UITabBarController {
            return true
        }
        return false
    }
}

Jonauz의 답변에 감사드립니다 . 다시 한 번 더 많은 최적화를위한 공간이 있습니다. 처리가 필요한 경우는 코멘트 란에서 상담해주십시오.


-1

궁금한 사람을 위해 ViewController에 표시되는 방법을 알려주는 방법

경우 A제시 / 밀어B

  1. 정의 enumproperty의를B

    enum ViewPresentationStyle {
        case Push
        case Present
    }
    
    //and write property 
    
    var vcPresentationStyle : ViewPresentationStyle = .Push //default value, considering that B is pushed 
  2. 이제 A뷰 컨트롤러에서 B할당하여 표시 / 푸시되고 있는지 확인합니다.presentationStyle

    func presentBViewController() {
        let bViewController = B()
        bViewController.vcPresentationStyle = .Present //telling B that it is being presented
        self.presentViewController(bViewController, animated: true, completion: nil)
    }
  3. BView Controller 에서의 사용법

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if self.vcPresentationStyle == .Present {
            //is being presented 
        }
        else {
            //is being pushed
        }
    
    }

-2
id presentedController = self.navigationController.modalViewController;
if (presentedController) {
     // Some view is Presented
} else {
     // Some view is Pushed
}

이것은 viewController가 표시되는지 또는 푸시되었는지 알려줍니다.


4
이 속성은 더 이상 사용되지 않습니다.
Morkrom
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.