调用setNeedsStatusBarAppearanceUpdate()后,prefersStatusBarHidden不更新

时间:2018-06-30 06:13:49

标签: swift uiviewcontroller uinavigationcontroller uiwindow uistatusbar

我的应用程序内的不同vc显示状态栏可见,而其他vc隐藏。在info.pList

中将其设置为YES。
 "View controller-based status bar appearance": YES

 // also tried togging this between yes and no
 "Status bar is initially hidden": YES

该应用程序有2个窗口,主窗口和第二个窗口。按下按钮,第二个窗口将显示在主窗口的前面。第二个窗口中的vc隐藏了状态栏。

问题是,如果我位于显示状态栏的主窗口内的vc(mainVC)上,则按下按钮以显示第二个窗口,mainVC的状态栏消失了。第二个窗口显示出来,我将其关闭后,我向mainVC发送通知以调用setNeedsStatusBarAppearanceUpdate(),但是prefersStatusBarHidden未被触发,因此状态栏保持隐藏,即使不应该隐藏。我什至为导航控制器创建了子类,并在其中添加了以mainVC为根的代码。

为什么没有prefersStatusBarHidden被打?

我将prefersStatusBarHidden单独添加到mainVC内,将nav单独添加到mainVC,然后同时添加了mainVC和它的nav。在任何一个地方setNeedsStatusBarAppearanceUpdate()被调用之后,它仍然没有被调用。

子类别的导航:

class MainVCNavController: UINavigationController {

    override init(rootViewController: UIViewController) {
        super.init(rootViewController: rootViewController)

        NotificationCenter.default.addObserver(self, selector: #selector(updateStatusBar), name: NSNotification.Name(rawValue: "updateStatusBar"), object: nil)
    }

    let statusBarHidden: Bool = false

    @objc func updateStatusBar() {
        self.setNeedsStatusBarAppearanceUpdate() // this gets called when the notification is triggered
    }

    override var prefersStatusBarHidden: Bool {
        return statusBarHidden // this doesn't get called after setNeedsStatusBarAppearanceUpdate() is called 
    }

    // I added this just to see if it would make a difference but it didn't
    override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
        return .slide
    }

    override open var childViewControllerForStatusBarStyle: UIViewController? {
        return self.topViewController
    }

    override open var childViewControllerForStatusBarHidden: UIViewController? {
        return self.topViewController
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }
}

MainVC是上述导航的rootVC

class MainVCController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(self, selector: #selector(updateStatusBar), name: NSNotification.Name(rawValue: "updateStatusBar"), object: nil)
    }

    let statusBarHidden: Bool = false

    @objc func updateStatusBar() {
        self.setNeedsStatusBarAppearanceUpdate() // this gets called when the notification is called
    }

    override var prefersStatusBarHidden: Bool {
        return statusBarHidden // this doesn't get called after setNeedsStatusBarAppearanceUpdate() is triggered 
    }

    // I added this just to see if it would make a difference but it didn't
    override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
        return .slide
    }
}

第二个窗口内的SecondVC隐藏了状态栏。当它被撤消时,它将通知发送到上述mainVC:

class SecondController: UIViewController {

    override var prefersStatusBarHidden: Bool {
        return true
    }

    if dismissed {
       NotificationCenter.default.post(name: Notification.Name(rawValue: "updateStatusBar"), object: nil)
    }
}

我还读到我需要调用以下内容来触发prefersStatusBarHidden,但是即使将它们添加到updateStatusBar()上也没什么作用。

navigationController?.setNavigationBarHidden(false, animated: false)
// or
navigationController?.navigationBar.isHidden = false

2 个答案:

答案 0 :(得分:1)

更新状态栏需要在主线程上。

有两种方法可以确保:

在主线程上添加通知观察器:(您无需将函数公开给objc c):

NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "updateStatusBar"), object: nil, queue: .main, using: updateStatusBar)

func updateStatusBar(_ notification: Notification) {
    setNeedsStatusBarAppearanceUpdate()
}

或更新主线程上的状态栏:

NotificationCenter.default.addObserver(self, selector: #selector(updateStatusBar(_:)), name: NSNotification.Name(rawValue: "updateStatusBar"), object: nil)

@objc func updateStatusBar(_ notification: Notification) {

    DispatchQueue.main.sync {
        self.setNeedsStatusBarAppearanceUpdate()
    }
}

答案 1 :(得分:0)

@zombie关于100%有效的主线程更新的答案。另一方面,他还建议我使用符号断点来诊断问题。他提供了一个很棒的帮助链接:

Symbolic Breakpoints