I have MapViewController embedded in a UINavigationController. I push to multiple view controllers from this view controller, pop to MapViewController from these view controllers.

In MapViewController I have google map its top position starts from safeAreaLayoutGuide. I hide and show the navigation controller based on multiple conditions. For example when I show subview1 I hide the navigation bar, when I show subview2 I show the navigation bar, etc...

Now I want to change the mapview top position whenever the navigation bar is visibility is changed.

How to solve this?

  • I checked UINavigationControllerDelegate. There is no delegate method called when navigation bar is shown/hidden where I can update the mapview top position.
  • viewDidLayoutSubviews is not called when navigation bar visibility changed. I want to do this in MapViewController only. Not in pushed view controller from this one.

1 Answers

PGDev On Best Solutions

You can add a property observer to the isHidden property of navigationBar and then observe any changes made, i.e.

var observer: NSKeyValueObservation?

override func viewDidLoad() {
    self.observer = self.navigationController?.navigationBar.observe(\.isHidden, options: [.new], changeHandler: { (navigationBar, changes) in
        if let newValue = changes.newValue {
            topConstraint.constant = newValue ? 0 : self.view.safeAreaInsets.top

When any changes are made in the isHidden property of navigationBar, we'll get a callback in the closure and act accordingly.