2

When I push, using storyboard segue, to the next view, it loads a space for the statusbar, even though the next view has set the prefersStatusBarHidden to false.

I have also tried by subclassing the UINavigationController and setting prefersStatusBarHidden to false in there, but still the view loads a space for it. Also automaticallyAdjustsScrollViewInsets is set to false.

Push to view

The view that is loaded consist of an UIViewController which has a UITableView. The background color of the UIViewController is (for testing) set to orange and the one for the table view is set to Pink. Neither of these colours are shown.

After som testing, it seems to me that the UINavigationController adds a space for its root view and removes that space after animating the push. If I set the background color of the UINavigationController to purple, I get the following result:

Result 2

This shows that the view it is pushing to is neither renedered nor in the correct Y position. I can't seem to find why this is.

My UINavigationController is contained in an UIViewController which has a container for the view (rootViewController). The navigation controller is create programatically whenever a root-page is requested to be loaded. This is that code:

/// Load a view controller with UINavigationController into the 
/// rootViewController and display it
///
/// - Parameter viewController: The view controller to show
func loadViewControllerPage(_ viewController: UIViewController) {
    let nav = UINavigationController(rootViewController: viewController)

    // No bar, please
    nav.isNavigationBarHidden = true

    // Make the view get in there propperly
    nav.willMove(toParentViewController: self)
    addChildViewController(nav)
    nav.view.willMove(toSuperview: rootViewController)
    nav.view.frame = rootViewController.bounds
    rootViewController.addSubview(nav.view)
    nav.view.didMoveToSuperview()
    nav.didMove(toParentViewController: self)
    rootViewController.bringSubview(toFront: nav.view)

    /* Test if this fixes the statusbar issue
    nav.edgesForExtendedLayout = .all
    nav.automaticallyAdjustsScrollViewInsets = false
    nav.extendedLayoutIncludesOpaqueBars = false
    */

    currentNav = nav

    // Cleanup
    for child in childViewControllers {
        if let c = child as? UINavigationController, c != nav && c.view.isDescendant(of: rootViewController) && c != menuView {
            c.removeFromParentViewController()
            c.view.removeFromSuperview()
        }
    }
}

Any suggestions on how I can solve this?

Paul Peelen
  • 10,073
  • 15
  • 85
  • 168

1 Answers1

3

Synopsis

  • Do not attempt to trigger iOS messages. Invoking didMoveToSuperview() programmatically is a sure sign that the design is likely flawed, or unnecessarily convoluted at best
  • No need to use loadViewControllerPage to push views onto a navigation controller or replace the root view controller
  • No need to programmatically create navigation controllers. Let Interface Builder prepare the resource for you, and load it on demand if you must.
  • The whole point of a navigation controller is to handle navigation ; do not bypass that mechanism and load views by hand

Notice how the status bar, visible on the orange view, isn't on the blue one. See animation.

Animation showing the status bar disappearing


Suggestions

When I push, using storyboard segue, to the next view, it loads a space for the statusbar, even though the next view has set the prefersStatusBarHidden to false.

Hiding Status Bar

To hide the status bar in your second view controller, set prefersStatusBarHidden to true, not false.

override var prefersStatusBarHidden:Bool {
    return true
}

Hiding Navigation Bar

If you do not want to display the navigation bar, change the Bar Visibility in the Navigation Controller Attributes Inspector.

Using storyboard segue

No code required for this. If you positively must use segues programmatically, see this StackOverflow answer.

Programmatically creating a Navigation Controller

No need to go through this path. Use a Storyboard ID to find and load the navigation controller from the storyboard.

UINavigationController subclass

Why so much code around loadViewControllerPage, and why subclassing UINavigationController?

Controlling custom transitions

If the object of your custom UIViewController loading is the animation, see this StackOverflow post.

Design transitions in the storyboard

Navigation Controller visibility, status bar visibility, segues, all defined by resources and yielding very little to no code.

enter image description here

Community
  • 1
  • 1
SwiftArchitect
  • 47,376
  • 28
  • 140
  • 179
  • Thank you for your elaborate answer. There are multiple reasons for your questions about custom navigation bar. The view _is_ pushing using segue (show). My bad on the `true` / `false` misstake, it was of course set to `true`. The reason for programatically creating the NavigationController is because the main storyboard has a container called `rootViewController`, in which a chosen view from the menu is loaded. The views loaded (such as Transaction history, account settings ect) have storyboard of their own. This makes the app more modular. – Paul Peelen Nov 28 '16 at 08:40
  • Thanks for the details. In truth, much of your problems stem from the highly customized `loadViewControllerPage` publish in your question. Replace it by a simple `rootViewController` property change at the window level if need be, but be not stopped by having multiple & nested navigation controllers. See http://stackoverflow.com/a/32390717/218152 for multiple nav controllers in a single storyboard. – SwiftArchitect Nov 28 '16 at 08:49
  • 1
    You answer, although it did not solve my issue, did gave me a different perspective of my implementation. I have refactored a lot and the code is a lot better now. The problem in the end was in the delegate of the UINavigationController where I changed the transition. This was due to the main navigation controller I used earlier, but didn't clean up properly. The problem is now solved. – Paul Peelen Nov 28 '16 at 10:37