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.


To handle this kind of behavior, I usually set/reset a BOOL toggling it in viewWillAppear/viewWillDisappear methods.

By the way, your test condition seems incorrect. I think you should use

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

Why can't you just always add the toolbar to your view controller? Is there any case the view is loaded but never presented?


I had a similar case, however the view controller that I presented is wrapped in it's own navigation controller. So in that view controller when I need to determine whether or not to add the close button vs a back button, I just check the navigation controllers stack size. If the screen is presented, the stack size should be one (needs close button)... and if it is pushed using an existing navigation controller, then stack size will be larger than one (needs back button).

BOOL presented = [[self.navigationController viewControllers] count] == 1;

I use the this code to check whether the UIViewController is presented.

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