【问题标题】:prefersStatusBarHidden not updating after calling setNeedsStatusBarAppearanceUpdate()调用 setNeedsStatusBarAppearanceUpdate() 后,prefersStatusBarHidden 不更新
【发布时间】:2018-12-09 06:28:23
【问题描述】:

我的应用程序中的不同 vcs 显示状态栏可见,而其他 vcs 则隐藏。这在 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 没有被调用?

我在 mainVC 中自己添加了prefersStatusBarHidden,在 mainVC 中自己添加了导航,然后在 mainVC 和它的导航中同时添加。在任一地方调用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是上述nav的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

【问题讨论】:

  • 您需要在可见控制器中写入prefersStatusBarHidden,即在第二个控制器中采取行动
  • 你是指第二个窗口吗?第二个窗口内的 vc,我们称之为 secondVC 确实将 prefersStatusBarHidden 设置为 true。它不显示状态栏。我会更新问题以显示它
  • 要了解我的意思,请查看answer
  • @zombie 我今天早上真的读到了,谢谢。在我读到它之后,我把它当作导航确定状态栏,因为它管理着一切。那时我将问题中的 navVC 子类化并在那里添加了 prefersStatusBarHidden 但它没有任何区别

标签: swift uiviewcontroller uinavigationcontroller uiwindow uistatusbar


【解决方案1】:

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

有两种方法可以确保:

在主线程上添加通知观察者:(不需要将func暴露给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()
    }
}

【讨论】:

  • @LanceSamaria 顺便说一句,如果您删除 deinit 中的观察者,那么您不需要 weak self
【解决方案2】:

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

Symbolic Breakpoints

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-06
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    • 1970-01-01
    • 2013-01-14
    • 2019-08-31
    相关资源
    最近更新 更多