暗模式和多窗口/场景

时间:2019-09-18 09:24:42

标签: ios13 uitraitcollection ios-darkmode

我正在尝试在多场景应用程序中实现ios13暗模式。

不幸的是,当我消除将场景拖到屏幕边缘时,以不同的值多次调用了traitCollectionDidChange方法,导致我的UI在暗和亮模式之间闪烁。

怎么了?

这是我的实现方式

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

    print("THEME instance: \(self)")  

    let currentTraitCollection = self.traitCollection  
    var hasUserInterfaceStyleChanged = false  
    hasUserInterfaceStyleChanged = previousTraitCollection.hasDifferentColorAppearanceCompared(to: currentTraitCollection)  

    print("THEME hasUserInterfaceStyleChanged = \(hasUserInterfaceStyleChanged ? "YES" : "NO")")  

    if hasUserInterfaceStyleChanged {  
        let userInterfaceStyle = currentTraitCollection.userInterfaceStyle // Either .unspecified, .light, or .dark  

        switch userInterfaceStyle {  
            case .unspecified:  
                print("THEME UIUserInterfaceStyleUnspecified")  
            case .light:  
                print("THEME UIUserInterfaceStyleLight")  
            case .dark:  
                print("THEME UIUserInterfaceStyleDark")  
            }  
    } else {  
        print("THEME NOT CHANGED")  
    }  

}  

这是控制台中记录的语句

当出现新场景时...

THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = YES  
THEME UIUserInterfaceStyleLight  

添加的场景消失后...

THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = YES  
THEME UIUserInterfaceStyleDark  
THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = YES  
THEME UIUserInterfaceStyleLight  
THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = NO  
THEME NOT CHANGED  
THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = YES  
THEME UIUserInterfaceStyleDark  
THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = YES  
THEME UIUserInterfaceStyleLight  

与此同时,我没有更改为暗模式(始终为亮)...所以我希望只是主题没有改变。

1 个答案:

答案 0 :(得分:2)

我一直在同一个问题上挣扎,而我解决的方法是在SceneDelegate中。

UIScene具有多种状态:

.foregroundActive
.foregroundInactive
.background
.unattached

当您要调整幻灯片上方窗口的大小,或者在这种情况下,要从幻灯片上方删除窗口时,traitCollectionDidChange会分别被调用。这意味着您正在为userInterfaceStyle.background.foregroundInactive状态的场景更新.unattached。这就是导致闪烁的原因。

解决方案是不使用traitCollectionDidChange,而是在SceneDelegate中使用名为windowScene(_:didUpdate:interfaceOrientation:traitCollection:)的委托方法。

每个Apple's docs使用此方法:

当场景的大小,方向或特征改变时通知您。

这样做的另一个好处是,我们可以在更新.activationState之前检查场景的userInterfaceStyle

    func windowScene(_ windowScene: UIWindowScene, didUpdate previousCoordinateSpace: UICoordinateSpace, interfaceOrientation previousInterfaceOrientation: UIInterfaceOrientation, traitCollection previousTraitCollection: UITraitCollection) {

          let currentTraitCollection = windowScene.traitCollection

          if windowScene.activationState == .foregroundActive {
             if currentTraitCollection.userInterfaceStyle != previousTraitCollection.userInterfaceStyle {
                 if currentTraitCollection.userInterfaceStyle == .light {
                     //update to light theme
                 } else {
                     //update to dark theme
                 }
             }
         }
     }