符合相关协议的对象的快速收集
问题描述:
我有一个问题(也许关于类型擦除)。想象一下以下情形:符合相关协议的对象的快速收集
public protocol DataItem {
associatedtype T
var action: ((_ item: T) -> Void)? {get}
}
struct UserItem: DataItem {
typealias T = UserItem
// Custom Properties
let name: String
// Protocol: DataItem
let action: ((T) -> Void)?
}
struct DriverItem: DataItem {
typealias T = DriverItem
// Custom Properties
let licenseNumber: String
// Protocol: DataItem
let action: ((T) -> Void)?
}
let items = [
UserItem(name: "Dexter", action: { (item) in print(item.name)}),
DriverItem(licenseNumber: "1234567890", action: { (item) in print(item.licenseNumber)})
]
items.forEach {
$0.action?($0)
}
我有一个DataItem的这是一个UITableViewCell一个抽象的数据项,其中有一个动作属性选择单元格时被调用。我的问题是如何创建一个DataItem对象数组,从这个列表中选择一个项目(或迭代它)并调用相应的操作,它将打印UserItem的名称和DriverItem的许可证编号。但是,与编译器上面实现以下消息抱怨说,项目清单只能是类型[任何] ...
Heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional
这样我可以不叫在协议的DataItem声明的行动。我试图环绕型擦除我的头,但不明白它尚未......如果有人想出了一个解决方案
会很高兴......
答
这并不难,没有额外的要求:
struct UserItem {
let name: String
func action() {
print(name)
}
}
struct DriverItem {
let licenseNumber: String
func action() {
print(licenseNumber)
}
}
let data = UserItem(name: "Test")
let closure = { print("Some object data \(data.name)") }
let items = [
UserItem(name: "Dexter").action,
DriverItem(licenseNumber: "1234567890").action,
closure
]
items.forEach {
$0()
}
答
的错误只是要求你一个类型添加到项目:
如果let items: Array<Any> = [
UserItem(name: "Dexter", action: { (item) in print(item.name)}),
DriverItem(licenseNumber: "1234567890", action: { (item) in print(item.licenseNumber)})
]
不知道这会不会导致更多的错误,因为我不知道,如果你可以调用完成块得到控制而e创建阵列。
编辑
我认为你正在尝试做的就是打电话时,该变量调用。做到这一点的方法是使用你已经输入的get
但没有完整的,就像这样:
var licenseNumber: String {
get {
print("doSomething!")
return self.licenseNumber
}
}
的阵列将成为类似:
let items: Array<Any> = [
UserItem(name: "Dexter"),
DriverItem(licenseNumber: "1234567890")
]
这看起来有点怪异,你'associatedtype'在'UserItem'(/'DriverItem /)'是'UserItem'(/'DriverItem /)本身,这意味着_instance_close'action'采用与拥有它的实例相同类型的单个参数。这是否如预期那样,例如给定的'UserItem'实例是对'UserItem'的_another_实例执行一个动作?我希望这个动作可以在实例本身而不是辅助外部实例上执行,但也许这是一个预期的设计选择。无论如何,如果是这样,你可以放弃'associatedtype',只需使用'Self'而不是'T'。 – dfri
它与UIControls中的目标/动作一样,旨在为操作方法中的发件人提供服务。发件人是项目本身。我希望能够在操作方法中使用具体类型的功能(如name和licenseNumber) - 你知道吗?重要的是,这些项目只存在于一个DataSource对象内,它不知道具体的类型。这就是为什么我不能直接访问具体类型的功能。我会尽快尝试你的方法。非常感谢:-) – blackjacx
Arg ....使用Self而不是T行为相同:'Protocol'DataItem'只能用作通用约束,因为它具有Self或关联类型要求。由于这种行为类型橡皮擦被写入。但我不明白如何正确地做到这一点......任何人的想法? – blackjacx