0

我经常通过以下方式使用语义颜色来为暗模式和亮模式提供动态颜色。使用这种方法,当用户切换暗/亮模式时,颜色也会在运行时更新:

public static var bw100: UIColor = {
    if #available(iOS 13, *) {
        return UIColor { (UITraitCollection: UITraitCollection) -> UIColor in
            if UITraitCollection.userInterfaceStyle == .dark {
                // Return the color for Dark Mode
                return .black
            } else {
                // Return the color for Light Mode
                return .white
            }
        }
    } else {
        // Return a fallback color for iOS 12 and lower.
        return .white
    }
}()

现在我想对一个Float值做同样的事情,比如有一个语义浮点变量。这意味着我可以为暗模式和亮模式访问不同的浮点值,并且如果用户切换暗/亮模式该值将在运行时适应。我找不到解决方案。

这不起作用,因为它不会在运行时更新。暗/亮模式切换后必须重新启动应用程序:

 public static var myFloat: Float = {
    if #available(iOS 13.0, *) {
        if UITraitCollection.current.userInterfaceStyle == .dark {
            return 0.9
        }
        else {
            return 0.1
        }
    }
    return 0.1
}()

这也不起作用(尝试了与上述工作类似的方法),但在这里我得到一个错误Initializer init(_:) requires that (UITraitCollection) -> Float conforms to BinaryInteger

public static var myFloat: Float = {
    if #available(iOS 13, *) {
        return Float { (UITraitCollection: UITraitCollection) -> Float in
            if UITraitCollection.userInterfaceStyle == .dark {
                // Return the Float for Dark Mode
                return 0.9
            } else {
                // Return the Float for Light Mode
                return 0.1
            }
        }
    } else {
        // Return a fallback for iOS 12 and lower.
        return 0.1
    }
}()
4

2 回答 2

1

这对我来说是实时的,并且非常接近你所拥有的:

static var myFloat : Float {
    let tc = UITraitCollection.current
    let mode = tc.userInterfaceStyle
    if #available(iOS 13.0, *) {
        return (mode == .light ? 1 : 0)
    }
    return 1
}

正如 Leo Dabus 所指出的,你所做的和我所做的唯一真正的区别是我有一个计算属性,每次你获取它的值时都会重新计算它,而你有一个定义和- 为初始化后永远不会更改的属性调用初始化程序。

于 2020-02-24T00:00:56.410 回答
1

您无法实现与UIColor使用 a Floatas的工作方式相同的东西,因为UIColor它有一个特殊的初始化程序,可以直接改变界面样式。然而,解决方案仍然相当简单,因为您必须如前所述,traitCollectionDidChange(_:)通过手动实现和重新计算数据来监听界面样式的变化。
以下代码应该为您实现它:

// ViewController.swift

var myStoredFloat: Float = 1.0 {
    willSet {
        print(newValue)
    }
}

var myComputedFloat: Float {
    let tc = UITraitCollection.current
    let mode = tc.userInterfaceStyle
    if #available(iOS 13.0, *) {
        return (mode == .light ? 1 : 0)
    }
    return 1
}

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    self.myStoredFloat = self.myComputedFloat
}

当然,如果您不依赖存储属性而只使用计算属性,则可以完全摆脱存储属性。

*感谢matt提供计算的属性代码。

于 2020-02-24T10:40:47.610 回答