【问题标题】:UINavigationController showing space for statusbar on pushUINavigationController 在推送时显示状态栏的空间
【发布时间】:2017-04-07 06:57:57
【问题描述】:

当我使用 storyboard segue 推送到下一个视图时,它会为状态栏加载一个空间,即使下一个视图已将 prefersStatusBarHidden 设置为 false

我也尝试过将UINavigationController 子类化并将prefersStatusBarHidden 设置为false,但视图仍然为它加载了一个空间。还将automaticallyAdjustsScrollViewInsets 设置为false

加载的视图由一个UIViewController 组成,该UITableView 具有一个UITableViewUIViewController 的背景颜色(用于测试)设置为橙色,表格视图的背景颜色设置为粉红色。这两种颜色都没有显示。

在 som 测试之后,在我看来 UINavigationController 为其根视图添加了一个空间,并在动画推送后删除了该空间。如果我将UINavigationController 的背景颜色设置为紫色,我会得到以下结果:

这表明它所推送的视图既没有被渲染,也没有处于正确的 Y 位置。我似乎无法找到这是为什么。

我的UINavigationController 包含在UIViewController 中,该UIViewController 有一个视图容器(rootViewController)。 每当请求加载根页面时,导航控制器都会以编程方式创建。这是代码:

/// 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()
        }
    }
}

关于如何解决这个问题的任何建议?

【问题讨论】:

  • adjustScrollViewInsets 可能会有所帮助
  • 已经将automaticallyAdjustsScrollViewInsets 设置为false,抱歉我没有提到。

标签: ios uitableview uinavigationcontroller swift3 xcode8


【解决方案1】:

概要

  • 不要尝试触发 iOS 消息。以编程方式调用 didMoveToSuperview() 是一个明确的迹象,表明设计可能存在缺陷,或者充其量是不必要的复杂
  • 无需使用loadViewControllerPage 将视图推送到导航控制器或替换根视图控制器
  • 无需以编程方式创建导航控制器。让 Interface Builder 为您准备资源,并在需要时按需加载。
  • 导航控制器的全部意义在于处理导航;不要绕过该机制并手动加载视图

请注意,在橙色视图上可见的状态栏不在蓝色视图上。 See animation.


建议

当我使用 storyboard segue 推送到下一个视图时,它会为状态栏加载一个空间,即使下一个视图已将 prefersStatusBarHidden 设置为 false.

隐藏状态栏

要在第二个视图控制器中隐藏状态栏,请将 prefersStatusBarHidden 设置为 true,而不是 false。

override var prefersStatusBarHidden:Bool {
    return true
}

隐藏导航栏

如果您不想显示导航栏,请在导航控制器属性检查器中更改 Bar Visibility

使用故事板转场

此操作无需代码。如果您肯定必须以编程方式使用 segue,请参阅 this StackOverflow answer

以编程方式创建导航控制器

无需走这条路。使用 Storyboard ID 从 Storyboard 中查找和加载导航控制器。

UINavigationController 子类

为什么loadViewControllerPage 周围有这么多代码,为什么要对UINavigationController 进行子类化?

控制自定义过渡

如果你自定义的UIViewController加载的对象是动画,见this StackOverflow post

故事板中的设计过渡

导航控制器可见性、状态栏可见性、segues,所有这些都由资源定义,几乎没有代码。

【讨论】:

  • 感谢您的详尽回答。您对自定义导航栏的问题有多种原因。视图 is 使用 segue (show) 推送。我对true / false 错误的看法很糟糕,它当然设置为true。以编程方式创建 NavigationController 的原因是主情节提要有一个名为 rootViewController 的容器,其中加载了从菜单中选择的视图。加载的视图(例如交易历史、帐户设置等)有自己的故事板。这使应用程序更加模块化。
  • 感谢您提供详细信息。事实上,您的大部分问题都源于您问题中高度定制的loadViewControllerPage 发布。如果需要,可以在窗口级别通过简单的rootViewController 属性更改来替换它,但不要因为拥有多个嵌套导航控制器而停止。请参阅stackoverflow.com/a/32390717/218152,了解单个故事板中的多个导航控制器。
  • 您的回答虽然没有解决我的问题,但确实让我对我的实施有了不同的看法。我已经重构了很多,代码现在好多了。最后的问题在于我更改了转换的 UINavigationController 的委托。这是由于我之前使用的主导航控制器,但没有正确清理。现在问题已经解决了。
猜你喜欢
  • 2013-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-14
  • 2015-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多