47

Possible Duplicate:
How to tell if UIViewController's view is visible

I'm developing an app that processes a constant stream of incoming data from the network and provides a number of different UIViews for the user to view that data.

When certain model data gets updated based on the incoming stream from the network, I access the associated UIViewController or UITableViewController and do -setNeedsDisplay on it (in the case of UIViewController) or -reloadData (in the case of UITableViewController).

Is there a way to check if a given UIView is currently being displayed (beyond just being loaded) so that I only do -setNeedsDisplay or -reloadData if the user is currently looking at that UIView? It would seem that calling -setNeedsDisplay or reloadData on a view that the user is not currently looking at is a waste of processing power and wouldn't be good for battery life. When the user eventually switches over to a view that previously got updated, doing -setNeedsDisplay or reloadData on the -viewWillAppear would make more sense.

Thanks

2
  • stackoverflow.com/questions/2777438/… Commented Nov 29, 2011 at 21:28
  • I can't add another answer, but there's now a property called isVisible on view controllers Commented Oct 4, 2017 at 7:18

3 Answers 3

135

After doing some research, I found this answer in a different question posted on here...This seems to be the best way...

The view's window property is non-nil if a view is currently visible, so check the main view in the view controller:

if (viewController.isViewLoaded && viewController.view.window){
    // viewController is visible
}
Sign up to request clarification or add additional context in comments.

7 Comments

I just edited the other question to also check isViewLoaded first to avoid accidently loading the view which this code above will do. Make the test: if (viewController.isViewLoaded && viewController.view.window) ...
This answer shouldn't really be marked as correct, since it will trigger the loading of the VC's view. See programer's answer linked above.
This will give you false positives for viewControllers that are obstructed by other, modally displayed viewControllers -> not the right way. What this does is reliable checking of a viewController is NOT visible, but not the other way around.
Technically speaking, this answer only indicates that the view is inside a window's view hierarchy. It doesn't say anything about the real visibility of that particular view (can be shifted away from screen, set hidden, or hidden by subviews...)
The comment is your code sample is misleading. Certainly there are cases where all your IF conditions are true and the viewController is NOT visible. For example, if the app is backgrounded.
|
14

Add this to your controllers, or to a subclass of UIViewController that you can then subclass further. Access it using a property or the variable:

- (void)viewDidAppear:(BOOL)animated
{
 [super viewDidAppear:animated];
 visible = YES;
}

- (void)viewWillDisappear:(BOOL)animated
{
 visible = NO;
 [super viewWillDisappear:animated];
}

4 Comments

Also, don't do this as a category. Redefining methods in a category is bad practice.
This would be a disaster in a category because you won't be able to define any class-specific behavior to occur on viewDidAppear or ViewWillAppear.
Of course you could still define class-specific behavior. You can override methods and still call the super method. This is an old post though, and I see that a category wouldn't be useful because you'd need to store visible. I'll edit it.
Using an instance variable here is not the best solution. A stateless solution like Paul suggested above is much better.
-3

Just for completeness, I thought I'd add in how to determine if the view controller is being displayed in a tab based app:

+(BOOL) isSelectedViewController:(UIViewController *)someVC;
{
    myAppDelegate   *appD = [[UIApplication sharedApplication] delegate];
    UIViewController *selectedVC = [appD.TabBarController selectedViewController];

    return selectedVC == someVC;
}

2 Comments

It would be much nicer to use (myViewController.tabBarController.selectedViewController == myViewController.navigationController), assuming you're nesting navigation controllers within the tab bar controller.
I suppose if you know that the sub-controller is a navigation controller, but that is often not the case.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.