首页 > 解决方案 > 如何检测 iOS 13 中的 Light\Dark 模式变化?

问题描述

某些 UI 设置无法自动使用暗/亮模式更改为UIColor. 例如shadow在层中。由于我需要在深色和浅色模式下移除和放置阴影,因此我需要在某个地方放置updateShadowIfNeeded()功能。我知道如何检测当前的模式:

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

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

override func layoutSubviews() {
    super.layoutSubviews()
    dropShadowIfNeeded()
}

但是这个函数被称为A LOT。只有在userInterfaceStyle更改时才触发的正确功能是什么?

标签: swiftuiuikitios-darkmodeuitraitcollection

解决方案


SwiftUI

键上有一个简单的环境变量\.colorScheme

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

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

UIKit

正如WWDC 2019 - 23:30 左右的Session 214中所述。

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

看一下该会话中的这张图片:

WWDC 2019 - 会议 214

灰色:打电话但对我的问题没有好处,绿色:为此而设计

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

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    
    if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
        dropShadowIfNeeded()
    }
}

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

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


推荐阅读