gpt4 book ai didi

ios - Swift 协议(protocol)、关联类型、Self 和默认实现的问题

转载 作者:行者123 更新时间:2023-11-28 11:45:35 35 4
gpt4 key购买 nike

我试图通过我无法确定的默认实现来获得一些功能。考虑以下代码,它是对我正在尝试做的事情的简化,但尽可能简单地捕获了问题。

//protocol definition
protocol Configurable {
associatedtype Data
func configure(data: Data)

static func generateObject() -> Self
}

//default implementation for any UIView
extension Configurable where Self: UIView {
static func generateObject() -> Self {
return Self()
}
}

//implement protocol for UILabels
extension UILabel: Configurable {
typealias Data = Int

func configure(data: Int) {
label.text = "\(data)"
}
}

//use the protocol
let label = UILabel.generateObject()
label.configure(data: 5)
print(label.text!) //5

我有一个协议(protocol),UIView 某些方法的默认实现,以及 UILabel 的特定实现。

我的问题是最后一部分......所有这些功能的实际使用

let label = UILabel.generateObject()
label.configure(data: 5)
print(label.text!) //5

我发现自己在做 generateObject()其次是 configure(data: <something>)不断地。所以我尝试执行以下操作:

添加static func generateObjectAndConfigure(data: Data) -> Self到协议(protocol)。当我尝试为此方法为 UIView 创建默认实现时,问题就出现了。我收到以下错误

Method 'generateObjectAndConfigure(data:)' in non-final class 'UILabel' cannot be implemented in a protocol extension because it returns本人and has associated type requirements

基本上,我没有返回 Self 的方法并使用关联类型。老是连续调用这两个方法,感觉真的很讨厌。我只想声明 configure(Data)对于每个类(class)并获得generateObjectAndConfigure(Data)免费。

有什么建议吗?

最佳答案

通过使用 Self,你有点过于复杂了。

所有你需要做的就是在你的 Configurable 协议(protocol)中声明一个初始化器,它接受你的 Data associatedtype 作为参数,并且有一个非-静态配置函数:

protocol Configurable {
associatedtype Data
init(data: Data)
func configure(data: Data)
}

Configurable 协议(protocol)(针对 UIView 及其子类)的扩展中提供该初始值设定项的默认实现:

extension Configurable where Self: UIView {
init(data: Data) {
self.init(frame: CGRect.zero)
self.configure(data: data)
}
}

最后,通过对您感兴趣的任何 UIView 子类的扩展来添加对协议(protocol)的一致性。您在这里需要做的就是实现 typealias配置方法:

extension UILabel: Configurable {
typealias Data = Int
func configure(data: Data) {
text = "\(data)"
}

extension UIImageView: Configurable {
typealias Data = String
func configure(data: Data) {
image = UIImage(named: data)
}
}

这个实现有一个额外的好处,你可以使用初始化器来创建你的 View (用于实例化对象的标准 Swift 模式),而不是静态方法:

let label = UILabel(data: 10)
let imageView = UIImageView(data: "screenshot")

我不太清楚为什么编译器不喜欢您的版本。我原以为 UILabel 的子类会继承 typealias 这意味着编译器在推断 Self 时应该没有问题数据,但显然这还不受支持。

编辑:@Cristik 在评论中提出了关于 UICollectionView 的一个很好的观点。

这个问题可以通过为 Configurable 添加协议(protocol)扩展来解决,其中 SelfUICollectionView,使用适当的初始化程序:

extension Configurable where Self: UICollectionView {
init(data: Data) {
self.init(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout())
self.configure(data: data)
}
}

然后,当为 UICollectionView 添加 Configurable 的一致性时,我们将 Data typealias 设为 UICollectionViewLayout:

extension UICollectionView: Configurable {
typealias Data = UICollectionViewLayout
func configure(data: Data) {
collectionViewLayout = data
}
}

就我个人而言,我认为对于 init(frame:) 初始化器不合适的类来说,这是一种合理的方法。

关于ios - Swift 协议(protocol)、关联类型、Self 和默认实现的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52618944/

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