如何检测 iOS 13 中的 Light\Dark 模式变化?

Moj*_*ini 8 uikit uitraitcollection swiftui ios-darkmode

某些 UI 设置无法在暗/亮模式下自动工作,因为UIColor. 例如shadow在图层中。因为我需要在明暗模式下删除和放置阴影,所以我需要在某个地方放置updateShadowIfNeeded()函数。我知道如何检测当前的模式:

func dropShadowIfNeeded() {
    switch traitCollection.userInterfaceStyle {
    case .dark: removeShadow()
    case .light: dropShadowIfNotDroppedYet()
    default: assertionFailure("Unknown userInterfaceStyle")
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我把这个函数放在 里面layoutSubviews,因为每次外观改变时它都会被调用:

override func layoutSubviews() {
    super.layoutSubviews()
    dropShadowIfNeeded()
}
Run Code Online (Sandbox Code Playgroud)

但是这个函数被调用了很多。只有在userInterfaceStyle更改时才触发的正确功能是什么?

Moj*_*ini 16

用户界面

\.colorScheme密钥上使用一个简单的环境变量:

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        Text(colorScheme == .dark ? "Its Dark" : "Its. not dark! (Light)")
    }
}
Run Code Online (Sandbox Code Playgroud)

用户界面工具包

正如它在WWDC 2019 - Session 214大约 23:30 中所述。

正如我所料,这个函数被调用了很多,包括颜色改变时。与许多其他功能一起用于ViewControllerpresentationController。但是有一些特殊的函数设计用于在所有View代表中具有相似的签名。

看看那次会议的这张图片:

WWDC 2019 - 会议 214

灰色:打电话但不适合我的问题,绿色:为此而设计

所以我应该调用它并在这个函数中检查它:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    
    if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
        dropShadowIfNeeded()
    }
}
Run Code Online (Sandbox Code Playgroud)

这将保证每次更改只调用一次。

如果您只是在寻找样式的初始状态,请在此处查看此答案

  • 灰色并不意味着“不好”,绿色并不意味着“为此而设计”。绿色突出显示仅表明演讲者正在谈论这些方法。(如果您后退几秒钟,您也会看到其他方法也以绿色突出显示。)如果我们给您留下了错误的印象,我很抱歉。 (4认同)