Detecting iOS Dark Mode Change

早过忘川 提交于 2019-12-23 09:01:22

问题


I read through the documentation regarding: https://developer.apple.com/documentation/appkit/supporting_dark_mode_in_your_interface

When the user changes the system appearance, the system automatically asks each window and view to redraw itself. During this process, the system calls several well-known methods for both macOS and iOS, listed in the following table, to update your content.

In our legacy app we create our views as lazy variables in the init of each class. This means thew won't get drawn out with the correct color if the user goes into settings and switches to dark mode.

If you make appearance-sensitive changes outside of these methods, your app may not draw its content correctly for the current environment. The solution is to move your code into these methods.

Our application is quite big and a refactor will be done to support this in a better way in the future but I'm wondering if there is a way to detect this changes with the notification center like what can be done for Mac OS:

How to detect switch between macOS default & dark mode using Swift 3


回答1:


Swift 5:

traitCollectionDidChange also gets called a few times. This is how I detect DarkMode runtime change and setColors() only once.

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)

        guard UIApplication.shared.applicationState == .inactive else {
            return
        }

        setColors()
    }

In setColors() func I update the colors. Detecting current colorScheme:

extension UIViewController {
    var isDarkMode: Bool {
        if #available(iOS 13.0, *) {
            return self.traitCollection.userInterfaceStyle == .dark
        }
        else {
            return false
        }
    }

}

I have colors defined like this (for iOS < 13):

enum ColorCompatibility {
    static var myOlderiOSCompatibleColorName: UIColor {
        if UIViewController().isDarkMode {
            return UIColor(red: 33, green: 35, blue: 37, alpha: 0.85)
        }
        else {
            return UIColor(hexString: "#F3F3F3", alpha: 0.85)
        }
    }
}

Example:

private func setColors() {
  myView.backgroundColor = ColorCompatibility.myOlderiOSCompatibleColorName
}

Also you might need to call setColors in ViewDidLoad/Will/DidAppear depending on your case like this:

viewDidLoad() {
...
setColors()
...
}

For iOS11+ you could use "named Colors", defined in Assets and much easier to use in IB.

Cheers




回答2:


in iOS Swift 5

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
  // Do sonthing
}



回答3:


I think for colors is better to use

UIColor.init { (trait) -> UIColor in

    return trait.userInterfaceStyle == .dark ? .label : .black
}

because this way if the system change, the color change too automatically.




回答4:


I ended up moving all my color setup to layoutSubviews() function in all views and the viewDidLayoutSubviews() in the view controllers.



来源:https://stackoverflow.com/questions/57706671/detecting-ios-dark-mode-change

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!