Antworten:
Da modalViewController
dies in iOS 6 veraltet ist, ist hier eine Version, die für iOS 5+ funktioniert und ohne Warnungen kompiliert wird.
Ziel c:
- (BOOL)isModal {
return self.presentingViewController.presentedViewController == self
|| (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController)
|| [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
}
Schnell:
var isModal: Bool {
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController)
|| self.tabBarController?.presentingViewController is UITabBarController
}
Hutspitze zu Felipes Antwort.
nil == nil
zurückgegeben YES
wird und es nicht das gewünschte Ergebnis ist.
Wenn Sie nach iOS 6+ suchen, ist diese Antwort veraltet und Sie sollten die Antwort von Gabriele Petronella überprüfen
Es gibt keine gute Möglichkeit, dies als Eigenschaft oder Methode von UIKit zu tun. Sie können verschiedene Aspekte Ihres Controllers überprüfen, um sicherzustellen, dass er als modal dargestellt wird.
Um zu überprüfen, ob der aktuelleself
Controller (wie im folgenden Code dargestellt) modal dargestellt wird oder nicht, habe ich den folgenden Balken entweder in einer UIViewController
Kategorie oder (wenn Ihr Projekt keine anderen UIKit-Controller verwenden muss, als UITableViewController
zum Beispiel) in einem Basis-Controller, von dem meine anderen Controller erben
-(BOOL)isModal {
BOOL isModal = ((self.parentViewController && self.parentViewController.modalViewController == self) ||
//or if I have a navigation controller, check if its parent modal view controller is self navigation controller
( self.navigationController && self.navigationController.parentViewController && self.navigationController.parentViewController.modalViewController == self.navigationController) ||
//or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
[[[self tabBarController] parentViewController] isKindOfClass:[UITabBarController class]]);
//iOS 5+
if (!isModal && [self respondsToSelector:@selector(presentingViewController)]) {
isModal = ((self.presentingViewController && self.presentingViewController.modalViewController == self) ||
//or if I have a navigation controller, check if its parent modal view controller is self navigation controller
(self.navigationController && self.navigationController.presentingViewController && self.navigationController.presentingViewController.modalViewController == self.navigationController) ||
//or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
[[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]]);
}
return isModal;
}
BEARBEITEN: Ich habe die letzte Überprüfung hinzugefügt, um festzustellen, ob ein UITabBarController verwendet wird, und Sie präsentieren einen anderen UITabBarController als modal.
BEARBEITEN 2: iOS 5+ Check hinzugefügt, wo UIViewController
nicht parentViewController
mehr geantwortet wird, sondern presentingViewController
stattdessen.
EDIT 3: Ich habe einen Kern dafür erstellt, nur für den Fall, dass https://gist.github.com/3174081
modalViewController
Eigenschaft ab iOS 6 veraltet ist. In der Dokumentation wird empfohlen, sie presentedViewController
stattdessen zu verwenden .
NSLog(@"%@", self.navigationController.parentViewController)
Drucke (null)
- können Sie bitte erklären, warum? Mein ViewController ist über navController im Storyboard mit dem Modal View Controller verbunden.
.parentViewController
ist veraltet, .presentingViewController
muss stattdessen verwendet werden.
In iOS5 + können Sie es, wie Sie in der UIViewController-Klassenreferenz sehen können, über die Eigenschaft "PresentingViewController" abrufen .
PresentingViewController Der View-Controller, der diesen View-Controller präsentiert hat. (schreibgeschützt)
@property (nichtatomar, schreibgeschützt) UIViewController * Präsentation der ViewController-
Diskussion
Wenn der Ansichtscontroller, der diese Nachricht empfangen hat, von einem anderen Ansichtscontroller angezeigt wird, enthält diese Eigenschaft den Ansichtscontroller, der sie anzeigt. Wenn der Ansichtscontroller nicht angezeigt wird, aber einer seiner Vorfahren angezeigt wird, enthält diese Eigenschaft den Ansichtscontroller, der den nächsten Vorfahren darstellt. Wenn weder der Ansichtscontroller noch einer seiner Vorfahren angezeigt wird, ist diese Eigenschaft gleich Null.
Verfügbarkeit
Verfügbar in iOS 5.0 und höher.
In
UIViewController.h deklariert
presentingViewController
. Es funktioniert auch in Containersicht-Controllern, da es automatisch die Vorfahren durchläuft.
Ist dies nicht der Fall , können Sie eine Eigenschaft für this ( presentedAsModal
) in Ihrer UIViewController-Unterklasse definieren und festlegen, YES
bevor Sie den ViewController als modale Ansicht präsentieren.
childVC.presentedAsModal = YES;
[parentVC presentModalViewController:childVC animated:YES];
Sie können diesen Wert in Ihrer viewWillAppear
Überschreibung überprüfen .
Ich glaube, es gibt keine offizielle Eigenschaft, die angibt, wie die Ansicht dargestellt wird, aber nichts hindert Sie daran, Ihre eigene zu erstellen.
UINavigationController
als modal präsentieren ... es sei denn, Sie erstellen einen benutzerdefinierten Navigationscontroller, um diese Eigenschaft hinzuzufügen. Und danach müssen Sie innerhalb der Controller self.navigationController
jedes Mal, wenn Sie überprüfen müssen, ob der Controller als modal dargestellt wird, in diese benutzerdefinierte Klasse
Petronellas Antwort funktioniert nicht, wenn self.navigationController modal dargestellt wird, aber self nicht gleich self.navigationController.viewControllers [0] ist. In diesem Fall wird self gedrückt.
Hier erfahren Sie, wie Sie das Problem beheben können.
return self.presentingViewController.presentedViewController == self
|| (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController && self == self.navigationController.viewControllers[0])
|| [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
Und in Swift:
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController && self.navigationController?.viewControllers[0] == self)
|| self.tabBarController?.presentingViewController is UITabBarController
Das sollte funktionieren.
if(self.parentViewController.modalViewController == self)…
UINavigationController
und UITabBarController
Fällen zu suchen . Es funktioniert bisher ziemlich gut
Beste Weg zu überprüfen
if (self.navigationController.presentingViewController) {
NSLog(@"Model Present");
}
Wenn Sie nicht zwischen modalen Vollbildansichten und nicht modalen Ansichten unterscheiden müssen, was in meinem Projekt der Fall ist (ich hatte ein Problem, das nur bei Formularblättern und Seitenblättern auftritt), können Sie den modalPresentationStyle verwenden Eigentum von UIViewController:
switch (self.modalPresentationStyle) {
case 0: NSLog(@"full screen, or not modal"); break;
case 1: NSLog(@"page sheet"); break;
case 2: NSLog(@"form sheet"); break;
}
In Swift :
func isUIViewControllerPresentedAsModal() -> Bool {
if((self.presentingViewController) != nil) {
return true
}
if(self.presentingViewController?.presentedViewController == self) {
return true
}
if(self.navigationController?.presentingViewController?.presentedViewController == self.navigationController) {
return true
}
if((self.tabBarController?.presentingViewController?.isKindOfClass(UITabBarController)) != nil) {
return true
}
return false
}
In meinem Projekt habe ich einen Ansichts-Controller (Detail), der entweder modal (beim Hinzufügen eines neuen Elements) oder per Push (beim Bearbeiten eines vorhandenen Elements) vom Master-Ansichts-Controller dargestellt werden kann. Wenn der Benutzer auf [Fertig] tippt, ruft der Detailansichts-Controller die Methode des Master-Ansichts-Controllers auf, um zu benachrichtigen, dass er zum Schließen bereit ist. Der Master muss festlegen, wie das Detail dargestellt wird, um zu wissen, wie es geschlossen werden kann. So mache ich das:
UIViewController *vc = self.navigationController.viewControllers.lastObject;
if (vc == self) {
[self dismissViewControllerAnimated:YES completion:NULL];
} else {
[self.navigationController popViewControllerAnimated:YES];
}
Ein Hack wie dieser könnte funktionieren.
UIViewController* child = self;
UIViewController* parent = child.parentViewController;
while (parent && parent.modalViewController != child) {
child = parent;
parent = child.parentViewController;
}
if (parent) {
// A view controller in the hierarchy was presented as a modal view controller
}
Ich denke jedoch, dass meine vorherige Antwort eine sauberere Lösung ist.
Was für mich funktioniert hat, ist Folgendes:
// this is the trick: set parent view controller as application's window root view controller
UIApplication.sharedApplication.delegate.window.rootViewController = viewController;
// assert no modal view is presented
XCTAssertNil(viewController.presentedViewController);
// simulate button tap which shows modal view controller
[viewController.deleteButton sendActionsForControlEvents:UIControlEventTouchUpInside];
// assert that modal view controller is presented
XCTAssertEqualObjects(viewController.presentedViewController.class, MyModalViewController.class);
Soweit ich es getestet habe, funktioniert dies für iOS7 und iOS8. Ich habe iOS6 jedoch nicht ausprobiert.
Ich habe mich ein bisschen umgesehen, um die richtige Antwort auf diese Frage zu finden, und ich konnte keine finden, die alle möglichen Szenarien abdeckte. Ich habe diese wenigen Codezeilen geschrieben, die den Job zu erledigen scheinen. Sie können einige Inline-Kommentare finden, um herauszufinden, was überprüft wurde.
- (BOOL)isModal {
BOOL modal = NO;
if ([self presentingViewController]) { //Some view Controller is presenting the current stack
UIViewController *presented = [[self presentingViewController] presentedViewController]; // What's been presented
if ([presented respondsToSelector:@selector(viewControllers)]) { // There's a stack
NSArray *viewControllers = [presented performSelector:@selector(viewControllers)];
modal = [viewControllers firstObject] == self; // Current VC is presented modally if it's the first in the stack
}
else {
modal = presented == self; // Don't think this is actually needed. set modal = YES should do the job tho.
}
}
return modal;
}
Ich hoffe das hilft.
Hier ist meine modifizierte Version von @ GabrielePetronella isModal
, die mit enthaltenen View-Controllern funktioniert, indem sie zuerst die parentViewController-Hierarchie aufruft. Ziehen Sie den Code auch in mehrere Zeilen heraus, damit klar ist, was er tut.
var isModal: Bool {
// If we are a child view controller, we need to check our parent's presentation
// rather than our own. So walk up the chain until we don't see any parentViewControllers
var potentiallyPresentedViewController : UIViewController = self
while (potentiallyPresentedViewController.parentViewController != nil) {
potentiallyPresentedViewController = potentiallyPresentedViewController.parentViewController!
}
if self.presentingViewController?.presentedViewController == potentiallyPresentedViewController {
return true
}
if let navigationController = potentiallyPresentedViewController.navigationController {
if navigationController.presentingViewController?.presentedViewController == navigationController {
return true
}
}
return potentiallyPresentedViewController.tabBarController?.presentingViewController is UITabBarController
}