Ios 使用关联类型快速收集符合协议的对象
我可能有一个关于类型擦除的问题。想象一下以下场景:Ios 使用关联类型快速收集符合协议的对象,ios,swift,protocols,type-erasure,swift4,Ios,Swift,Protocols,Type Erasure,Swift4,我可能有一个关于类型擦除的问题。想象一下以下场景: public protocol DataItem { associatedtype T var action: ((_ item: T) -> Void)? {get} } struct UserItem: DataItem { typealias T = UserItem // Custom Properties let name: String // Protocol: Dat
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的一个抽象数据项,它有一个action属性,在选择单元格时应该调用该属性。我的问题是如何创建一个DataItem对象数组,从列表中选择一个项目,或者迭代该项目并调用相应的操作,该操作将打印UserItem的名称和DriverItem的许可证号。但是在上面的实现中,编译器会用以下消息抱怨条目列表只能是[Any]类型
异类集合文字只能推断为“[任何]”;如果有意这样做,请添加显式类型注释
这样我就不能调用协议数据项中声明的操作。我试图把我的头缠在字型擦除上,但还不能理解它
如果有人能想出一个解决方案,我会很高兴…没有额外的要求,这并不难:
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)})
]
该数组将变成如下所示:
let items: Array<Any> = [
UserItem(name: "Dexter"),
DriverItem(licenseNumber: "1234567890")
]
动作闭包被认为是一个可以从外部设置的闭包,而不是一个静态函数。你可以将任何具有正确签名的闭包放入数组中-你不能让闭包使用不同的参数。您还可以将带有标题示例和void闭包的结构放在适当的数组中。仍然无法调用类似items.forEach{$0.action?$0}的操作方法,因为items包含您案例中的任何对象。我想我搜索的是类型橡皮擦模式,但我不确定如何正确实现它。@blackjacx如果let item=$0 as,我会这样做吗?UserItem{item.actionitem}与其浪费大量时间尝试解决它,不如在UserItem/DriverItem/is UserItem/DriverItem/is中关联类型,这看起来有点奇怪,这意味着实例闭包操作采用与拥有它的实例相同类型的单个参数。例如,给定的UserItem实例将对UserItem的另一个实例执行操作,这是否符合预期?我希望在实例本身而不是次要外部实例上执行操作,但这可能是一个预期的设计选择。无论如何,如果是这样,您可以松开associatedtype,只使用Self而不是T。它与uicontrol中的目标/操作类似,用于在操作方法中提供发送者。发送者就是项目本身。我希望通过这种方式,可以在action方法中使用具体类型的功能,如name和licenseNumber,你知道吗?重要的是,这些项只存在于不知道具体类型的DataSource对象中。这就是我无法直接访问具体类型功能的原因。我会尽快尝试你的方法。非常感谢:-Arg。。。。使用Self而不是T的行为相同:协议“DataItem”只能用作泛型约束,因为它具有Self或关联的类型要求。由于这种行为类型的橡皮擦被写入。但我不知道如何正确地做。。。有人有主意吗?
let items: Array<Any> = [
UserItem(name: "Dexter"),
DriverItem(licenseNumber: "1234567890")
]