1

I have an application which has more than one view. When I return to the foreground from the background, I want to determine which view I am in presently. How would I do that?

[EDIT]

I understand visibleViewController property of navigationController might help. But, I want to know how to use the pointer returned by it in my comparison with a UIViewController object. How can we compare pointers? Some code snippets would be very helpful.

Namratha
  • 16,630
  • 27
  • 90
  • 125

4 Answers4

3

zirinisp's Answer in Swift:

extension UIWindow {
    func visibleViewController() -> UIViewController? {
        if let rootViewController: UIViewController  = self.rootViewController {
            return UIWindow.getVisibleViewControllerFrom(rootViewController)

    }
    return nil
}

class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {
if vc.isKindOfClass(UINavigationController.self) {

    let navigationController = vc as UINavigationController
    return UIWindow.getVisibleViewControllerFrom( navigationController.visibleViewController)

} else if vc.isKindOfClass(UITabBarController.self) {

    let tabBarController = vc as UITabBarController
    return UIWindow.getVisibleViewControllerFrom(tabBarController.selectedViewController!)

} else {

    if let presentedViewController = vc.presentedViewController {

        return UIWindow.getVisibleViewControllerFrom(presentedViewController)

    } else {

        return vc;
    }
}
}

Usage:

if let topController = window.visibleViewController() {
            println(topController)
        }
Bobj-C
  • 5,276
  • 9
  • 47
  • 83
2

In depends on what root view controller you're using. If you have a navigation controller, you can check the visibleViewController property to see which view controller is currently on top of the navigation stack. For a tab bar controller, check the selectedViewController property to see which tab is active. If it's a combination of the two, use both methods in tandem.

Each of the container view controllers provide some way or another to figure out what's selected or currently on screen. If you're doing your own special setup, you'll have to come up with a good way to determine this information on your own.

CIFilter
  • 8,647
  • 4
  • 46
  • 66
  • ..and if your using neither tab bar or navigation bar? What would you suggest? – bandejapaisa Sep 21 '11 at 11:37
  • Well in that case, you're probably just using your own root view controller, so it should be obvious which one is visible at launch. – CIFilter Sep 21 '11 at 11:47
  • I'm using navigationController. The visibleViewController returns a UIViewController. How do I check for equality with the UIViewController that I want – Namratha Sep 21 '11 at 12:55
  • I'm not sure I understand. If your app resumes from being background, it will put you back at the view controller you were in previously. Asking the navigation controller for the visible view controller gives you that context. – CIFilter Sep 21 '11 at 13:37
  • Ok I'll elaborate. I have two views, say A and B. When I return to the foreground from the background, I want to do something only if it is view A. You are right in saying the same view that was there before entering background will be loaded again. But how do I find out from which view the user entered background-A or B? – Namratha Sep 22 '11 at 04:08
  • Store a (weak) reference to both of the view controllers (I presume you meant view controller; you shouldn't be working directly with views at the app delegate level) in the app delegate. When it resumes from the background, compare the currently visible controller with your references. – CIFilter Sep 22 '11 at 07:43
  • 1
    Couldn't you just use the viewwill/didappear to perform some action on a viewcontroller when it appears? – Mike Mellor Sep 04 '13 at 12:52
1

I always love solutions that involve categories as they are bolt on and can be easily reused.

So I created a category on UIWindow. You can now call visibleViewController on UIWindow and this will get you the visible view controller by searching down the controller hierarchy. This works if you are using navigation and/or tab bar controller. If you have another type of controller to suggest please let me know and I can add it.

UIWindow+PazLabs.h (header file)

#import <UIKit/UIKit.h>

@interface UIWindow (PazLabs)

- (UIViewController *) visibleViewController;

@end

UIWindow+PazLabs.m (implementation file)

#import "UIWindow+PazLabs.h"

@implementation UIWindow (PazLabs)

- (UIViewController *)visibleViewController {
    UIViewController *rootViewController = self.rootViewController;
    return [UIWindow getVisibleViewControllerFrom:rootViewController];
}

+ (UIViewController *) getVisibleViewControllerFrom:(UIViewController *) vc {
    if ([vc isKindOfClass:[UINavigationController class]]) {
        return [UIWindow getVisibleViewControllerFrom:[((UINavigationController *) vc) visibleViewController]];
    } else if ([vc isKindOfClass:[UITabBarController class]]) {
        return [UIWindow getVisibleViewControllerFrom:[((UITabBarController *) vc) selectedViewController]];
    } else {
        if (vc.presentedViewController) {
            return [UIWindow getVisibleViewControllerFrom:vc.presentedViewController];
        } else {
            return vc;
        }
    }
}

@end
zirinisp
  • 9,971
  • 5
  • 32
  • 38
1

You want to know when you app came into the foreground and became active. This needs to be somewhere at the root of your view controller hierarchy - possibly your AppDelegate, possibly your root view controller.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appActive:)
                                                 name:UIApplicationDidBecomeActiveNotification 
                                               object:nil];

In appActive:(NSNotification *)notification; or whatever method you call it - do what LucasTizma suggested.

Also remember to clean up your notifcations when you're done

 [[NSNotificationCenter defaultCenter] removeObserver:self];
bandejapaisa
  • 26,576
  • 13
  • 94
  • 112