ios - 当用户在设置中更改外观时,应用程序不会更新并且 traitCollectionDidChange 不会触发

标签 ios swift ios-darkmode uitraitcollection

在我的应用程序中,我允许用户覆盖设备上设置的外观。如果他们想覆盖系统范围的外观,这是处理更新 UI 的类:

class UserInterfaceStyleController {

init() {
    self.handleUserInterfaceStyleChange()
    NotificationCenter.default.addObserver(self, selector: #selector(self.handleUserInterfaceStyleChange), name: Notification.Name(OMGNotification.changeBizzaroMode.rawValue), object: nil)
}

@objc func handleUserInterfaceStyleChange() {
    if #available(iOS 13.0, *) {
        let windows = UIApplication.shared.windows
        for window in windows {
            if UIScreen.main.traitCollection.userInterfaceStyle == .light {
                if UserDefaults.standard.bizzaroMode {
                    window.overrideUserInterfaceStyle = .dark
                } else {
                    window.overrideUserInterfaceStyle = .light
                }
            }
            if UIScreen.main.traitCollection.userInterfaceStyle == .dark {
                if UserDefaults.standard.bizzaroMode {
                    window.overrideUserInterfaceStyle = .light
                } else {
                    window.overrideUserInterfaceStyle = .dark
                }
            }
            window.subviews.forEach({ view in
                view.layoutIfNeeded()
            })
        }
    }
}

这是有效的 - 用户翻转开关,应用程序更改 userInterfaceStyle。问题是当用户更改系统范围的外观(在设置中设置亮或暗模式)时,应用程序不会自动更改外观,只有当他们手动设置时。

所以我假设当用户在系统范围内更改它时我需要做一些工作,而 traitCollectionDidChange 似乎是我需要使用的。问题是当用户在设置中更改外观时它不会触发,只有在我的应用程序中手动设置时才会触发。
我在 viewController 中有这个代码来测试:
class ViewController: UIViewController, UIGestureRecognizerDelegate {

    // Lots of stuff

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        print("We have a style mode change")
    }

    // Lots more stuff
}

当我手动覆盖时,它会打印“我们有一个样式模式更改”。当我进入设置并切换系统范围的外观时,traitCollectionDidChange 不会触发。

我发誓我在某一时刻工作得很好,但是当我使用 overrideUserInterfaceStyle 并且经历了很多代码更改时,我一直在尝试解决一些奇怪的问题。

我想我错过了一些明显的东西。在我开始允许用户覆盖之前,当外观在系统范围内更改时,应用程序在后台自动切换,根本没有代码。现在它不会并且 traitCollectionDidChange 不会触发。我错过了什么或做错了什么?如果有帮助,很高兴提供更多代码。

谢谢!

最佳答案

问题是您覆盖了用户界面样式,这会导致任何系统更改不会传播到您的窗口。您需要设置overrideUserInterfaceStyle.unspecified ,否则系统不会调用 traitCollectionDidChange View 堆栈中的方法发生变化。

在我们的应用程序中,我们为用户提供了三个选项:自动、亮和暗,其中每个选项只是设置 overrideUserInterfaceStyle到适当的选项。

顺便说一句,你不需要打电话layoutIfNeeded()在您的所有 subview 上—设置 overrideUserInterfaceStyle自动触发重绘。

关于ios - 当用户在设置中更改外观时,应用程序不会更新并且 traitCollectionDidChange 不会触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60532920/

相关文章:

ios - iTunes Connect 中的 App Icon 会覆盖 iTunesArtwork.png 图片吗?

ios - 应用商店拒绝应用后如何重新上传应用

ios - 如何访问 iOS13 之前的 UIImage 深色外观

arrays - 循环总是返回最后一张图片

ios - SwiftUI:在设备上测试时未检测到深色模式

ios - 如何为 iOS 设置包中的 slider 指定暗/亮模式图像?

ios - 我可以在相机胶卷上获取视频的绝对 URI 并从我的应用程序中对其进行变异吗?

ios - Swift IAP 稍后从 json 响应中获取latest_receipt_info 值

ios - 尝试在 Swift 中设置 UISwitch 的初始状态

ios - 本地notifications是否可以swift从web上下载信息