私のアプリでは、ユーザーがデバイスに設定されている外観をオーバーライドできるようにしています。システム全体の外観をオーバーライドしたい場合に、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 は起動しません。私は何が欠けているか、間違っていますか? 役立つ場合は、より多くのコードを提供してください。
ありがとう!