Wie kann ich in meiner Ansicht Controller-Code unterscheiden:
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.
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;
}
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
}
}
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
}
}
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
}
}
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.
Swift 4
var isModal: Bool {
return presentingViewController != nil ||
navigationController?.presentingViewController?.presentedViewController === navigationController ||
tabBarController?.presentingViewController is UITabBarController
}
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;
}
}
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
}
self.navigationController != nil
würde bedeuten, dass es sich in einem Navigationsstapel befindet.
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 ...
if navigationController.presentingViewController != nil {
// Navigation controller is being presented modally
}
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;
}
}
if let navigationController = self.navigationController, navigationController.isBeingPresented {
// being presented
}else{
// being pushed
}