programing

뷰 컨트롤러가 모듈식으로 표시되는지 내비게이션 스택에서 푸시되는지 확인하는 방법은 무엇입니까?

jooyons 2023. 5. 20. 10:46
반응형

뷰 컨트롤러가 모듈식으로 표시되는지 내비게이션 스택에서 푸시되는지 확인하는 방법은 무엇입니까?

내 보기 컨트롤러 코드에서 다음을 구별하는 방법은 무엇입니까?

  • 형식적으로 제시된
  • 탐색 스택에서 푸시됨

둘다요.presentingViewController그리고.isMovingToParentViewController이다YES두 경우 모두, 그것은 별로 도움이 되지 않습니다.

문제를 복잡하게 만드는 것은 제 상위 뷰 컨트롤러가 때때로 모달로 되어 있어서 확인할 뷰 컨트롤러가 눌러져 있다는 것입니다.

내 문제는 내가 내 것을 내장한다는 것입니다.HtmlViewController순식간에UINavigationController그런 다음 표시됩니다.그렇기 때문에 저만의 시도와 아래의 좋은 답변들이 효과가 없었습니다.

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

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

제 생각에는 제 뷰 컨트롤러가 모달일 때 결정하려고 하지 말고 말씀드리는 것이 좋을 것 같습니다.

테스트하지 않은 소금 한 알과 함께 복용합니다.

- (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;
 }

Swift에서:

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

// 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
    }
}

한 가지 방법을 간과했습니다.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
    }
}

스위프트 5
다음은 이전 답변과 함께 언급된 문제를 해결하는 솔루션입니다.isModal()돌아온다true밀리면UIViewController프레젠테이션에 있습니다.UINavigationController겹겹이 쌓다

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
        }
    }
}

아직까지는 효과가 있습니다.일부 최적화된 경우 공유하십시오.

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
        }
    }
}

스위프트 5.깔끔하고 단순합니다.

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

스위프트 4

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

스위프트 5
이 편리한 확장 기능은 이전 답변보다 몇 가지 더 많은 사례를 처리합니다.이러한 경우에는 VC(view controller)가 앱 창의 루트 VC이고 VC가 상위 VC에 하위로 추가됩니다.보기 컨트롤러가 형식적으로 표시된 경우에만 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
    }
}

요나우즈의 대답 덕분에.여기에도 더 많은 최적화를 위한 공간이 있습니다.처리가 필요한 건에 대해서는 코멘트란에서 협의 부탁드립니다.

모듈식으로 표시하는 모든 viewController가 새 탐색 컨트롤러(항상 이를 수행해야 함) 안에 있다고 가정하면 이 속성을 VC에 추가할 수 있습니다.

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

    return false
}

여기 있는 많은 사람들이 제안하듯이, "확인" 방법이 모든 경우에 적합하지는 않습니다. 제 프로젝트에서 저는 수동으로 관리할 수 있는 해결책을 생각해 냈습니다.요점은, 우리는 보통 발표를 스스로 관리한다는 것입니다. 이것은 현장 뒤에서 일어나는 일이 아니며 우리는 반성해야 합니다.

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:

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

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

컨트롤러가 눌린 것을 감지하거나 원하는 곳에서 아래 코드를 사용하지 않는 경우:

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

    // Not pushed
}
else {

    // Pushed
}

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

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;
    }
}
if let navigationController = self.navigationController, navigationController.isBeingPresented {
    // being presented
}else{
    // being pushed
}

iOS 15 및 Xcode 13.1에서 테스트한 이 솔루션은 어떻습니까?

var isPresented: Bool {
    if let nvc = navigationController {
        return nvc.viewControllers.firstIndex(of: self) == 0
    } else {
        return presentingViewController != nil
    }
}

self.navigationController != nil내비게이션 스택에 있다는 뜻입니다.

ViewController에 표시되는 정보를 알려주는 방법에 대해 궁금해하는 사람들을 위해

한다면A presenting/missing /시pushing시중표▁isB

  1. 를 합니다.enum그리고.propertyB

    enum ViewPresentationStyle {
        case Push
        case Present
    }
    
    //and write property 
    
    var vcPresentationStyle : ViewPresentationStyle = .Push //default value, considering that B is pushed 
    
  2. 지은금에서A, Tell 보롤러트컨, 시표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. 에서 B

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if self.vcPresentationStyle == .Present {
            //is being presented 
        }
        else {
            //is being pushed
        }
    
    }
    
id presentedController = self.navigationController.modalViewController;
if (presentedController) {
     // Some view is Presented
} else {
     // Some view is Pushed
}

그러면 viewController가 표시되는지 또는 푸시되는지 알 수 있습니다.

언급URL : https://stackoverflow.com/questions/23620276/how-to-check-if-a-view-controller-is-presented-modally-or-pushed-on-a-navigation

반응형