更新视图控制器之间的状态栏样式

时间:2017-12-15 18:27:04

标签: ios swift statusbar

在我的info.plist文件中,View controller-based status bar appearance设置为YES

我有一个隐藏状态栏的FirstViewController

SecondViewController我有

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

override var prefersStatusBarHidden: Bool {
    return false
}

override func viewDidLoad() {
    super.viewDidLoad()

    setNeedsStatusBarAppearanceUpdate()
}

但是,状态栏显示为黑色。

如何让它正确更新?感谢

编辑:

AppDelegate.swift也有此

UIApplication.shared.statusBarStyle = .lightContent

中的

didFinishLaunchingWithOptions

4 个答案:

答案 0 :(得分:17)

Info.plist文件中有一个名为查看基于控制器的状态栏外观的属性。它应设置为。 然后在你的UIViewController中你应该覆盖preferredStatusBarStyle

override var preferredStatusBarStyle : UIStatusBarStyle {
    return .lightContent
}

需要注意的一件重要事情是:如果您将视图控制器嵌入到UINavigationController中并且您的视图控制器的preferredStatusBarStyle方法未被调用 - 您将不得不通过编写如下内容来解决此问题:

extension UINavigationController {
    override open var preferredStatusBarStyle : UIStatusBarStyle {
        return topViewController?.preferredStatusBarStyle ?? .default
    }
}

它所做的只是向顶级控制器询问其状态栏样式,并进行适当更新

答案 1 :(得分:9)

当您的视图控制器是导航控制器的子节点时,如何管理状态栏样式会产生很多误解。

您的子视图控制器可以实现preferredStatusBarStyle,如果导航栏隐藏,这将正常工作。

如果导航栏显示,导航控制器会根据导航栏的barStyle - 设置状态栏样式,如果是样式,则设置为.default如果条形样式为.default,则为.lightContent.blackviewWillAppear。因此,当导航栏显示时,视图控制器设置状态栏样式的正确方法是设置导航控制器的导航栏样式。

显而易见的地方是override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.navigationController?.navigationBar.barStyle = .black // or .default } ,只要这个视图控制器成为导航控制器堆栈的顶部,就会调用它:

var source = { links: { source: "0000", target: "1234", bond: "1111" }, nodes: { id: "01234", atom: "CHHHH" } },
    target = {};

Object.keys(source).forEach(function (k) {
    target[k] = target[k] || [];
    Object.keys(source[k]).forEach(function (l) {
        var i;
        for (i = 0; i < source[k][l].length; i++) {
            target[k][i] = target[k][i] || {};
            target[k][i][l] = source[k][l][i];
            //        ^--------------------^
        }
    });
});

console.log(target);

答案 2 :(得分:0)

还有UINavigationController的替代解决方案。您可以将其子类化,并结合使用childForStatusBarHiddensetNeedsStatusBarAppearanceUpdate()属性。

class StatusBarNavigationController: UINavigationController {
    override var childForStatusBarHidden: UIViewController? {
        return topViewController
    }

    override var viewControllers: [UIViewController] {
        didSet { setNeedsStatusBarAppearanceUpdate() }
    }
}

因此状态栏样式将由topViewController定义。

答案 3 :(得分:0)

Swift 5,iOS 12

这里的大多数答案都很有帮助,但并没有立即为我解决问题。我有一个嵌套结构(根VC>标签栏VC>导航VC>特定页面VC),我希望其中一个推送的页面VC更改状态栏的颜色。

在VC页中设置navigationBar.barStyle对我没有任何帮助,可能是因为导航VC并不是顶级VC。设置preferredStatusBarStyle在页面VC中也不起作用(尽管如果我在根VC中覆盖了此属性,它也可以工作)。

@kelin的回答使我朝着正确的方向前进。 childForStatusBarStyle帮助指定应检查哪个子VC的样式正确。这是我采取的步骤:

步骤1 :为我的VC层次结构中的所有VC实施childForStatusBarHidden

例如用于根VC

override var childForStatusBarStyle: UIViewController? {
  // this is a custom var I've set up
  return currentViewController
}

用于VC标签

override var childForStatusBarStyle: UIViewController? {
  return selectedViewController
}

对于导航VC

override var childForStatusBarStyle: UIViewController? {
  return topViewController
}

步骤2 :确保正确调用childForStatusBarStyle。在检查iOS之前未设置我的根VC的currentViewController变量,因此我需要在设置该变量后调用setNeedsStatusBarAppearanceUpdate()来指示需要再次检查childForStatusBarStyle

第3步:在确定状态栏外观的子VC中,覆盖样式:

override var preferredStatusBarStyle: UIStatusBarStyle {
  return .lightContent
}

步骤4 :确保在创建子VC时调用setNeedsStatusBarAppearanceUpdate(),并从根控制器中调用它。因此,子级VC中的setNeedsStatusBarAppearanceUpdate()无法正常工作,但例如UIApplication.shared.keyWindow?.rootViewController?.setNeedsStatusBarAppearanceUpdate()做到了。

第5步:当子VC从层次结构中删除并且您想要恢复状态栏样式时,请确保再次从根VC调用setNeedsStatusBarAppearanceUpdate(),也许在viewWillDisappear

请注意,上述解决方案不需要我将View controller-based status bar appearance Info.plist值显式设置为YES,这是许多答案所引用的。