wake-up-neo.com

So stellen Sie fest, dass ein UIViewController dargestellt wird

Ich habe eine UIViewController-Unterklasse erstellt, die entweder in einen Navigations-Stack eines UINavigationControllers gepusht oder von einem beliebigen UIViewController (modal) dargestellt werden kann. Ich muss feststellen, ob mein View-Controller angezeigt wird. Wenn er angezeigt wird, muss ich eine Symbolleiste mit einer Schließen-Schaltfläche am oberen Rand des View-Controllers hinzufügen. (Andernfalls wird die Standardschaltfläche zum Schließen hinzugefügt, indem der Benutzer im Navigationsstapel gedrückt wird. Dadurch kann der Benutzer zurückkehren.)

In allen verfügbaren Versionen sagen Sie 4.3, 5.0 bis 6.0 aus einer UIViewController-Unterklasse. Kann ich davon ausgehen, dass der View-Controller (modal) dargestellt wird, wenn die folgende Bedingung erfüllt ist.

if(self.parentViewController == nil || self.navigationController == nil)
25
saikamesh

Mit iOS 5 erhielt UIViewController eine Readonly-Eigenschaft namens presentingViewController, die die ältere Semantik von parentViewController (die jetzt containment beschreibt) ersetzt. Diese Eigenschaft kann verwendet werden, wenn ein View-Controller an den View-Controller gelangen muss, der ihn präsentiert. Beachten Sie: Dies ist oft etwas anderes als Sie erwarten, wenn Sie mit der API neu sind!

Darüber hinaus wurde die isBeingPresented-Eigenschaft eingeführt, um die Klasse der Situationen, in denen Sie sich gerade befinden, zu lösen. Überprüfen Sie diese Eigenschaft im viewWillAppear: Ihres View-Controllers.

Aktualisieren

Ich habe gelesen, dass Sie auch iOS 4.3 als Ziel haben:
In diesem Fall müssen Sie den Aufruf von isBeingPresented mit einer if ([self respondsToSelector:…]) überwachen. Sie können dann im else-Block prüfen, ob der parentViewController nicht gleich null ist.

Ein weiterer Ansatz für die Abwärtskompatibilität könnte darin bestehen, +resolveInstanceMethod: zu überschreiben, um eine Implementierung für -isBeingPresented zur Laufzeit hinzuzufügen. Dadurch bleiben Ihre aufrufenden Sites sauber und Sie werden Runtime-Magie los, sobald Sie die alte iOS-Unterstützung aufgeben. ;-)

Beachten Sie jedoch, dass es Edge-Fälle gibt, und Sie beginnen auch, wenn Sie auf iOS <5 laufen:

Der View-Controller kann in einem beliebigen anderen View-Controller enthalten sein, einschließlich Navigations-Controller. Wenn der letzte Fall eintritt, haben Sie kein Glück: parentViewController wird nil sein, während navigationController nicht ist. Sie können versuchen, schwerfälligen Code hinzuzufügen, um diese Einschränkung in älteren iOS-Versionen abzumildern. Oder Sie lassen es einfach los.

31
danyowdee

Ich verwende den folgenden Code, um zu überprüfen, ob der UIViewController dargestellt wird.

if (uiviewcontroller.presentingViewController != nil) {
   // do something
}
10
Evelyn Loo

Um mit dieser Art von Verhalten umzugehen, setze ich normalerweise ein BOOL, das es in den viewWillAppear/viewWillDisappear-Methoden umschaltet.

Ihre Testbedingung scheint übrigens falsch zu sein. Ich denke du solltest verwenden

if(self.parentViewController != nil || self.navigationController != nil)

Warum können Sie die Symbolleiste nicht immer zu Ihrem View Controller hinzufügen? Gibt es einen Fall, dass die Ansicht geladen wird, aber nie dargestellt wird?

7
Gl0ub1l

Ich hatte einen ähnlichen Fall, aber der von mir präsentierte View-Controller ist in seinen eigenen Navigationscontroller eingebunden. Wenn ich also in diesem Ansichts-Controller feststellen muss, ob die Schließen-Schaltfläche gegenüber der Zurück-Schaltfläche hinzugefügt werden soll, prüfe I einfach die Stack-Größe der Navigations-Controller. Wenn der Bildschirm angezeigt wird, sollte die Stapelgröße eins sein (Schaltfläche zum Schließen des Fensters) ... und wenn er mit einem vorhandenen Navigationscontroller gedrückt wird, ist die Stapelgröße größer als eins (Schaltfläche "Zurück").

BOOL presented = [[self.navigationController viewControllers] count] == 1;
7
Martin M Reed

@saikamesh.

Wenn Sie UINavigationController zum Navigieren in den ViewControllern verwenden, können Sie topViewController ( Doc hier ) und visibleViewController ( Doc again ) verwenden, um Ihre Absicht zu erreichen.

Sie erwähnen das:

wenn es im Navigationsstapel gedrückt wird, wird die Standardschaltfläche zum Schließen wird hinzugefügt, indem der Benutzer zurückkehren kann

Wenn die Instanz des spezifischen UIViewControllers wichtig ist, denke ich, dass es besser ist, eine gemeinsam genutzte Singleton-Instanz zu erstellen und ein global präsentiertes Flag bereitzustellen:

id specificVC = [SpecificViewController sharedInstance];
if (specificVC.isPushed) {
    [self.navController popToViewController:specificVC animated:YES];
}

und um zu überprüfen, ob es präsentiert wird:

if ([self.navController.visibleViewController isKindOfClass:[SpecificViewController class]]) {
    // Hide or add close button
    self.isPresented = YES;
}

Oder Sie können die viel akzeptierte Antwort lesen.

:) Hoffnung hilft.

3
Jason Lee

Sie könnten es so machen, es ist schnell und sicher 

UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

// Find the top controller on the view hierarchy
while (topController.presentedViewController) {
    topController = topController.presentedViewController;
}

// If the top controller it is not already presented
if (![topController isKindOfClass:[YourViewController class]]) {
    // Present it
    [topController presentViewController:yourViewController animated:YES completion:nil];
}
else {
// do some stuff here
}
2

Bitte überprüfen Sie diesen Weg:

 for (UIViewController*vc in [self.navigationController viewControllers]) {
    if ([vc isKindOfClass: [OffersViewController class]]){ //this line also checks OffersViewController is presented or not 

        if(vc.isViewLoaded){
             NSLog(@"Yes");
        }

    }
}
2
Banker Mittal

Eine elegante Antwort, die ich hier nicht gesehen habe:

// Edit: Added 2 other modal cases
extension UIViewController {
    var isModal: Bool { 
        return self.presentingViewController?.presentedViewController == self
            || (navigationController != nil && navigationController?.presentingViewController?.presentedViewController == navigationController)
            || tabBarController?.presentingViewController is UITabBarController
    }
}

gutschrift: basierend auf diesem Gist

1
AmitaiB

Sie können jederzeit überprüfen, ob Sie einen Controller für modale Ansichten haben oder nicht, indem Sie die Eigenschaft modalViewController Ihres Navigationscontrollers verwenden. Ex:

   UIViewController *presentedController = self.navigationController.modalViewController;
   if (presentedController) {
      // At this point, you have a view controller presented from your navigation controller
      if ([presentedController isKindOfClass:[controllerYouWantToCheck class]]) {
         // add your toolbar/buttons/etc here
      }
   }
1
Vlad

In Swift unter iOS 9 (oder neuer):

if viewController.viewIfLoaded?.window != nil {
    // viewController is visible
}
1
Ali A. Jalil

Wenn ich es wäre, hätte ich eine benutzerdefinierte init-Methode und verwende diese beim Erstellen des Vc.

vc = [[[MyUIViewControllerSubClass alloc] init] initWithToolbarAndCloseButton:YES];
0
ader

Wie Martin Reed sagte, ist dies der beste Weg

            BOOL presented = [[self.navigationController viewControllers] count] == 1;
        if (presented) {
            [self dismissViewControllerAnimated:YES completion:^{
                // do whatever you need here
            }];
        }
        else {
            [self.navigationController popViewControllerAnimated:YES];
        }
0
oskarko

Kleine Änderung in der Antwort von @AmitaiB zum Erstellen einer Funktion 

func isModallyPresented(tmpVC:UIViewController) -> Bool {
        return tmpVC.presentingViewController?.presentedViewController == tmpVC
            || (tmpVC.navigationController != nil && tmpVC.navigationController?.presentingViewController?.presentedViewController == tmpVC.navigationController)
            || tmpVC.tabBarController?.presentingViewController is UITabBarController
    }

Einfach per Anruf prüfen:

if(isModallyPresented(tmpVC:myTopVC)){
//return true if viewcontroller is presented 
}
0
HDdeveloper