How to Check If a View Controller Is Presented Modally or Pushed on a Navigation Stack

How to check if a view controller is presented modally or pushed on a navigation stack?

Take with a grain of salt, didn't test.

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

How to identify that an UIViewController is presented

With iOS 5, UIViewController gained a readonly property named presentingViewController, that replaces the older semantics of parentViewController (which now describes containment). This property can be used when a view controller needs to get at the view controller that’s presenting it — note: this will often be something else than what you’d expect, if you’re new to the API!

In addition, the isBeingPresented property had been introduced to pretty much solve the class of situations you’re currently in. Check for this property in your view controller’s viewWillAppear:.

Update

I overread that you seem to target iOS 4.3 as well:

In that case, you need to guard the call to isBeingPresented with an if ([self respondsToSelector:…]) you can then in the else block check for whether the parentViewController is not nil.

Another approach to backwards compatibility might be to override +resolveInstanceMethod: to add an implementation for -isBeingPresented at runtime. This will leave your calling sites clean, and you’d get rid of runtime-magic as soon as you let go of ancient iOS support ;-)

Note, though, that there are edge cases to this, and you initial approach as well, when running on iOS <5:

The view controller can be presented contained in any other view controller—including navigation controllers. When that last case happens, you’re out of luck: parentViewController will be nil, while navigationController will not. You can try to add gobs of unwieldy code to mitigate this limitation in older iOSes…or you could just let it go.

Determining if a UIViewController is being presented modally

Got an answer on Twitter. I ended up subclassing UITabBarController and adding a BOOL isModal instance property which is set to YES when presenting modally. Then subviews can use self.tabBarController with a cast to the subclass to access the isModal property and render/behave accordingly.

How to check if navigation controller is pushed or is a root view controller?

[self.navigationController viewControllers];

will return an array of all the viewControllers on the stack. Simply compare the first element in this array to see is the controller the root or not.

e.g.

UIViewController *vc = [[self.navigationController viewControllers] firstObject];

if([vc isEqual: ])
{
// code here
}

EDIT: Add Swift

let vc = self.navigationController?.viewControllers.first
if vc == self.navigationController?.visibleViewController {
//Code Here
}

How do I check if an UIViewController is currently being displayed?

You need to check if your viewcontroller is on top of the stack of navigationcontroller's viewcontroller array. A sample code is,

if (self.navigationController.topViewController == self) {
//the view is currently displayed
}

You can use this inside the viewWillAppear method to check whether the current view is visible.

How to detect if a pushed viewcontroller appears again?

To know if an instance of cvB's class exists in the navigation stack, you could use this piece of code:

let result = self.navigationController?.viewControllers.filter({
if let vcB = $0 as? UIViewController { // Replace UIViewController with your class, for example ViewControllerB
return true
}
return false
})

if result.isEmpty {
print("An instance of vcB's class hasn't been pused before")
} else {
print("An instance of vcB's class has been pused before")
}


Related Topics



Leave a reply



Submit