0

Note:

  • I am not using a UINavigationController.
  • I have a UIViewController called ContainerViewController which has 3 child view controllers that acts similar to a UIPageViewController, but it is not a UIPageViewController, it's contains a paging UIScrollView instead. Each child view controller then is able to instantiate other view controller's modally.

I want to refresh a view controller when coming back from the background. However, this should only happen if when you return from the background, that view controller is the visible one (meaning top most and active).

Question is: How do I determine if a view controller is the one that is visible (top most and active on screen now)?

If I use an answer from this question: Get top most UIViewController

extension UIApplication {
    class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }
        if let tabController = controller as? UITabBarController {
            if let selected = tabController.selectedViewController {
                return topViewController(controller: selected)
            }
        }
        if let presented = controller?.presentedViewController {
            return topViewController(controller: presented)
        }
        return controller
    }
}

This works. But if I leave the app in a child view controller of ContainerViewController, this extension just returns ContainerViewController -> not the child view controller.

Any thoughts?

Community
  • 1
  • 1
JEL
  • 1,540
  • 4
  • 23
  • 51

1 Answers1

0

You know you're going to need this information, so it's just a matter of planning ahead. Each time you switch pages in the scroll view, use your knowledge of the child view controllers and the pages to record, in a property of the container view controller, what view controller's view is showing now. Now all your routine has to do is consult that property.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • hm interesting, so in `ContainerViewController` I could have a property called `currentVisibleVC` or something but where would you update this property -> would you use a `UIScrollView` delegate method (not sure which one is best)? – JEL Apr 29 '17 at 03:58
  • That is certainly what I had in mind, yes. You always know through the delegate where the user has scrolled to. – matt Apr 29 '17 at 03:59
  • I cannot resist commenting, however, that all this would be a lot simpler if you _had_ used a UIPageViewController. – matt Apr 29 '17 at 03:59
  • Sure thanks! We did paging scrollView cause of certain restrictions. Since your the expert, what is your take on which delegate method to use from `UIScrollView` in order to update that property? It seems there are conflicts of which to use here: http://stackoverflow.com/questions/5272228/detecting-uiscrollview-page-change – JEL Apr 29 '17 at 04:00
  • I actually have some example code that shows you how to calculate which page of a paging scroll view the user has paged to: https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch07p372paging/ch20p676paging/ViewController.swift It does this in the context of tying the scroll view to a page control, something that you might like to do in your app, actually. – matt Apr 29 '17 at 04:01
  • Wow nice! And that answers the question of which delegate method to use, which is: `scrollViewDidEndDecelerating` – JEL Apr 29 '17 at 04:03
  • Of course, you don't really need the property; you _could_ just perform this same calculation in your routine. You know the content offset so you know the page so you know the view controller. – matt Apr 29 '17 at 04:03
  • Yeah for sure, makes sense. Thanks a lot for helping out! – JEL Apr 29 '17 at 04:05