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

8

22

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

My UIViewControllers are listening for NSNotifications - even if when they are not displayed (ie not shown). So I could have 10 UIViewController in the background observing NSNotifications from NSNotificationCenter. When an NSNotification is posted and received by the UIViewController, I'd like to find out if it is currently being shown. If it is not, I will just set a boolean so that it will processed when the View is presented. If it currently being display, I will do more things like update tables immediately, and so forth...

Bonaire answered 9/10, 2012 at 20:29 Comment(4)
How are you presenting view controller's view ?Android
@tdubik: the traditional way, like pushViewController. I'm not using StoryBoard or segues.Bonaire
In such case you can check topViewController from UINavigationController class. Or if you want to process more then one controller enumerate viewControllers array.Android
Answers to your question aside, why don't you just ditch the NSNotifications, create a BOOL called isVisible and set the value when viewDidAppear and viewDidDisappear are called? Then in your viewWillAppear (or wherever) you can just check your BOOL and loose a whole lot of complexity.Zonked
T
21

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.

Tuatara answered 9/10, 2012 at 22:26 Comment(2)
@DBD's answer is a more generic one and since the question title is not that specific, will be more helpful to future readers.Detriment
What about a pageviewcontroller? What is the "self.nav" equivalent? Like.. self.page..?Biliary
Z
12

Check to see if it's attached to the window. If it's not nil it's in hierarchy which is attached to the screen (of course it could be off the bounds of the screen, covered by some other view or have the hidden flag set)

if (myViewController.view.window) {
  // I'm attached to the window
} else {
  // not attached to the window
}
Zonked answered 9/10, 2012 at 20:56 Comment(4)
Close, but you should check whether the view is loaded before checking whether the view is in window: if (self.isViewLoaded && self.view.window != nil) ...Douai
@rob. Yes, you are correct. If the view controller is not loaded and you access the view object, you'll cause lazy loading which could mean loading things into memory you aren't really ready to use. While it would still give the correct answer, it would present less than ideal performance. I had made the assumption that notifications would only be added when the view is loaded, not initialized, since an uninitialized view will never be attached. Still it was possibly an inappropriate assumption and one which should have been stated if nothing else.Zonked
This should really be the correct answer, with @robmayoff's change integrated.Flocculant
agreed to @Bill... This should indeed be the accepted answer!Hypertensive
E
3

You can use flags in viewWillAppear and viewWillDisappear methods for this.

Eyesore answered 9/10, 2012 at 22:34 Comment(0)
F
1

Why don't you remove the notification listener in viewWillDisappear and add it in viewWillAppear?

Edit: misread his question, sorry.

Suggested answer: set your own flag (BOOL) in viewDidDisappear and viewDidAppear.

Floatable answered 9/10, 2012 at 20:37 Comment(5)
This won't work because it will miss all the notifiations when it removed.Bonaire
Then what about setting a flag (BOOL) in viewWillDisappear to indicate the view is not visible anymore. When it receives a notification, check the flag to see if the view is visible.Floatable
If the notification comes I will need to reload the table. If it does not come, then it is too expensive to do that. Further, there is no need to reload the table when the view re-appears for the same reason: data is the same and too expensive.Bonaire
You mean I set a flag MYSELF when the view disappears? It is a strange solution, because I thought Apple's API has thought about that I can can detect it. How?Bonaire
I see what you mean; I was thinking about if you're pushing a view as a modal VC with a transparent background, if you'd consider the bottom view as visible or not. I would set my own flag because it gives me more control. I do not know if view.superview (other answer) will work but it seems plausible.Floatable
D
1

Specify title to each ViewController and then get the title of current ViewController by the code given bellow.

NSString *currentController = self.navigationController.visibleViewController.title;

Then check it by your title like this

if([currentController isEqualToString:@"myViewControllerTitle"]){

    //write your code according to View controller. 

}
Delapaz answered 19/8, 2013 at 9:15 Comment(0)
A
0

I think that checking of viewController.view.superview should works.

Android answered 9/10, 2012 at 20:45 Comment(4)
I don't really understand. How do you make the comparison?Bonaire
if(viewController.view.superview != nil )Android
The problem is, your view could be attached to a superview, but that superview might not be attached to your window so there is a potential loophole where it won't work.Zonked
When this loop hole could happened in case of viewControllers ?Android
F
0

It's too late to replay on this question.

To check the instance of a UIViewController is currently on the top of the screen or to check if it is showing on screen, you can put a check like:

// Get the topmost view showing on the screen as below
    UIViewController * currentVC = ((UINavigationController*)app.window.rootViewController).visibleViewController;

// Now check whether the viewcontroller you want to show is the same as the currently showing view controller.
    if (currentVC.class == myVC.class) {  // Here myVC is any/new instance of the viewcontroller you would like to check or show (if not shown).
         // If both are same then it returns true and executes this block of code.
    }
Ferd answered 25/6, 2019 at 9:1 Comment(0)
C
0

One more alternative which is based on checking window property

if viewController.viewIfLoaded?.window != nil {
    // visible
}
Chaney answered 3/4, 2021 at 8:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.