0

I want to display some UI elements, like a search bar, on top of my app's first VC, and also on top of a second VC that it presents.

My solution for this was to create a ContainerViewController, which calls addChildViewController(firstViewController), and view.addSubview(firstViewController.view). And then view.addSubview(searchBarView), and similar for each of the UI elements.

At some point later, FirstViewController may call present(secondViewController), and ideally that slides up onto screen with my search bar and other elements still appearing on top of both view controllers.

Instead, secondViewController is presented on top of ContainerViewController, thus hiding the search bar.

I also want, when a user taps on the search bar, for ContainerViewController to present SearchVC, on top of everything. For that, it's straightforward - containerVC.present(searchVC).

How can I get this hierarchy to work properly?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Andrew
  • 7,693
  • 11
  • 43
  • 81
  • 1
    Using containerviewcontroller looks a good approach. Just that when u want to present the second controller you can use custom view animation or navigation based transitions that transitions the secondVC as it is same as if you used `present(secondViewController)`.This way the top most UI elements will not hide. – iAviator Oct 23 '17 at 15:35

1 Answers1

0

If I understand correctly, your question is how to present a view controller on top (and within the bounds) of a child view controller which may have a different frame than the bounds of the parent view. That is possible by setting modalPresentationStyle property of the view controller you want to present to .overCurrentContext and setting definesPresentationContext of your child view controller to true.

Here's a quick example showing how it would work in practice:

override func viewDidLoad() {
    super.viewDidLoad()

    let childViewController = UIViewController()
    childViewController.view.backgroundColor = .yellow
    childViewController.view.translatesAutoresizingMaskIntoConstraints = true
    childViewController.view.frame = view.bounds.insetBy(dx: 60, dy: 60)
    view.addSubview(childViewController.view)
    addChildViewController(childViewController)
    childViewController.didMove(toParentViewController: self)

    // Wait a bit...
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
        let viewControllerToPresent = UIViewController()
        viewControllerToPresent.modalPresentationStyle = .overCurrentContext // sets to show itself over current context
        viewControllerToPresent.view.backgroundColor = .red

        childViewController.definesPresentationContext = true // defines itself as current context
        childViewController.present(viewControllerToPresent, animated: true, completion: nil)
    }
}
Au Ris
  • 4,541
  • 2
  • 26
  • 53