gpt4 book ai didi

ios - 使用泛型扩展 UIView

转载 作者:行者123 更新时间:2023-11-28 05:39:33 25 4
gpt4 key购买 nike

我正在编写一个 ThemeCoordinator 来管理 View 的外观。这是一个如何设置协调的示例:

label.coordinate(\.textColor, light: .black, dark: .white)

如您所见,它简明扼要、易于阅读。这是幕后发生的事情:

extension UIView {
func coordinate<T>(_ keyPath: ReferenceWritableKeyPath<UIView, T>, light lightValue: T, dark darkValue: T) {
// This line adds a closure to the ThemeCoordinator
ThemeCoordinator.shared.coordinate(self, keyPath, light: lightValue, dark: darkValue)
}
}

不过,细心的人会注意到,第一个代码块不应该编译:关键路径和扩展名是为 UIView 指定的,这意味着 UIView.coordinate 只能采用对所有 UIView 有效的关键路径。所以,\.backgroundColor 会起作用,但 \.textColor 不会。

下面的函数有效,但我希望它作为一个扩展而不是一个全局函数:

func coordinate<View: UIView, Value>(_ view: View, _ keyPath: ReferenceWritableKeyPath<View, Value>, light lightValue: Value, dark darkValue: Value) {
ThemeCoordinator.shared.coordinate(view, keyPath, light: lightValue, dark: darkValue)
}

我可以这样调用(也可读,但我更喜欢扩展名):

coordinate(label, \.textColor, light: .black, dark: .white)

如何使这个函数成为 UIView 扩展?

最佳答案

理想情况下你想要的是像下面这样的东西,但我们目前不能像这样在类扩展中使用 Self:

// Will not compile due to this error:
// 'Self' is only available in a protocol or as the result of a method in a class
extension UIView {
func coordinate<T>(_ keyPath: ReferenceWritableKeyPath<Self, T>, light lightValue: T, dark darkValue: T) {
ThemeCoordinator.shared.coordinate(self, keyPath, light: lightValue, dark: darkValue)
}
}

但是,我们可以通过定义协议(protocol)和该协议(protocol)的扩展来解决这个问题,如下所示:

protocol ThemeCoordinatable: UIView {}

extension ThemeCoordinatable {
func coordinate<T>(_ keyPath: ReferenceWritableKeyPath<Self, T>, light lightValue: T, dark darkValue: T) {
ThemeCoordinator.shared.coordinate(self, keyPath, light: lightValue, dark: darkValue)
}
}

extension UIView: ThemeCoordinatable {}

首先,我们定义了一个名为 ThemeCoordinatable 的协议(protocol)并对其进行约束,以便只有 UIView 可以符合此协议(protocol)。然后,我们在此协议(protocol)上定义一个扩展,并在其上实现 coordinate 方法,使用 Self 而不是 UIView。 (Swift 允许我们在协议(protocol)扩展中这样做,但出于某种原因不允许类扩展。)由于所有 ThemeCoordinatable 必须是 UIViewSelf还必须是某种 UIView

然后,最后要做的就是让 UIView 符合 ThemeCoordinatable。没有这个,ThemeCoordinatable 并没有真正做很多事情,因为我们将无法在任何 UIView 或子类上调用此 coordinate 方法的 UIView

最后,在这里使用它:

let view = UIView()
view.coordinate(\.backgroundColor, light: .white, dark: .black)

let label = UILabel()
label.coordinate(\.textColor, light: .black, dark: .white)

let slider = UISlider()
slider.coordinate(\.maximumValue, light: 2.0, dark: 1.0)

关于ios - 使用泛型扩展 UIView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57334294/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com