it-swarm.com.de

Prüfen Sie, ob der View Controller modal dargestellt oder auf einem Navigationsstapel verschoben wird

Wie kann ich in meiner Ansicht Controller-Code unterscheiden:

  • modal dargestellt
  • auf Navigationsstapel gedrückt

Sowohl presentingViewController als auch isMovingToParentViewController sind in beiden Fällen YES und daher nicht sehr hilfreich.

Kompliziert ist, dass mein übergeordneter View-Controller manchmal modal ist, auf den der zu überprüfende View-Controller verschoben wird.

Es stellt sich heraus, dass ich meine HtmlViewController in eine UINavigationController einbettete, die dann präsentiert wird. Deshalb haben meine eigenen Versuche und die guten Antworten unten nicht funktioniert.

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

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

Ich denke, ich sollte meinem View-Controller besser sagen, wann er modal ist, anstatt zu versuchen, es zu bestimmen.

91
meaning-matters

Nehmen Sie mit einem Körnchen Salz, nicht getestet.

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

Sie haben eine Methode übersehen: isBeingPresented.

isBeingPresented ist wahr, wenn der View-Controller dargestellt wird, und falsch, wenn gedrückt wird.

- (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
    }
}
65
rmaddy

In 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 || false
    }
}
57
King-Wizard

self.navigationController! = nil würde bedeuten, dass es sich in einer Navigation befindet Stapel.

Um den Fall zu behandeln, dass der aktuelle View-Controller gedrückt wird, während der Navigationscontroller modal dargestellt wird, habe ich einige Codezeilen hinzugefügt, um zu überprüfen, ob der aktuelle View-Controller der Root-Controller im Navigationsstapel ist.

extension UIViewController{
func isModal() -> Bool {

    if let navigationController = self.navigationController{
        if navigationController.viewControllers.first != self{
            return false
        }
    }

    if self.presentingViewController != nil {
        return true
    }

    if self.navigationController?.presentingViewController?.presentedViewController == self.navigationController  {
        return true
    }

    if self.tabBarController?.presentingViewController is UITabBarController {
        return true
    }

    return false
   }
}
18
Jibeex

Swift 3
Hier ist eine Lösung, die das in den vorherigen Antworten erwähnte Problem anspricht, wenn isModal()true zurückgibt, wenn UIViewController in einem präsentierten UINavigationController-Stack gedrückt wird.

extension UIViewController {
    var isModal: Bool {
        if let index = navigationController?.viewControllers.index(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
        }
    }
}

Bei mir klappt das soweit ... Bei einigen Optimierungen bitte teilen.

17
Jonauz

Swift 4

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

Wie viele Leute hier vermuten, dass "Prüfmethoden" nicht in allen Fällen gut funktionieren, habe ich in meinem Projekt eine Lösung gefunden, um das manuell zu verwalten. Dies geschieht nicht hinter den Kulissen, und wir müssen nach innen schauen.

DEViewController.h datei:

#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

Die Präsentationen konnten jetzt so verwaltet werden:

auf Navigationsstapel gedrückt:

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

modal mit Navigation dargestellt:

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

modal dargestellt:

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

In DEViewController könnten wir einen Fallback hinzufügen, um zu prüfen, ob die oben genannte Eigenschaft gleich SSViewControllerPresentationMethodUnspecified ist:

- (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
Yevhen Dubinin

Vorausgesetzt, dass alle von Ihnen modulierten viewControllers in einen neuen navigationController eingebunden sind (was Sie immer tun sollten), können Sie diese Eigenschaft Ihrem VC hinzufügen.

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

    return false
}
3
Demosthese

self.navigationController != nil würde bedeuten, dass es sich in einem Navigationsstapel befindet.

2
Daniel

Um zu erkennen, dass Ihr Controller an beliebiger Stelle gedrückt wird oder nicht einfach unterhalb des Codes verwendet wird:

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

    // Not pushed
}
else {

    // Pushed
}

Ich hoffe, dass dieser Code jedem helfen kann ...

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

Wenn Sie iOS 5.0 oder höher verwenden, verwenden Sie bitte diesen Code

-(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
Shahbaz Abbasi
if let navigationController = self.navigationController, navigationController.isBeingPresented {
    // being presented
}else{
    // being pushed
}
0
mkto