简体   繁体   English

Swift集合对象的协议与关联类型

[英]Swift Collection Of Objects Conforming To Protocol With Associatedtype

I have a question (maybe regarding type erasure). 我有一个问题(也许关于类型擦除)。 Imagine the following scenario: 想象以下情况:

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)
}

I have a DataItem which is an abstract data item for a UITableViewCell and which has an action property that should be called when the cell is selected. 我有一个DataItem,它是UITableViewCell的抽象数据项,并且具有一个action属性,当选择单元格时应调用该action属性。 My question is how can I create an array of DataItem objects, select an item from this list (or iterate over it) and call the respective action, that will print the name of the UserItem and the license number of the DriverItem. 我的问题是如何创建一个DataItem对象数组,从该列表中选择一个项目(或对其进行迭代),然后调用相应的操作,该操作将打印UserItem的名称和DriverItem的许可证号。 But with that implementation above the compiler complains with the following message that the items list can only be of type [Any]... 但是在上面的实现中,编译器抱怨以下消息,即项目列表只能是[Any]类型。

Heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional

That way I cannot call the action declared in the protocol DataItem. 这样,我将无法调用协议DataItem中声明的操作。 I tried to wrap my head around type erasures but couldn't understand it yet... 我试图绕过类型擦除,但还不明白...

Would be happy if anyone comes up with a solution... 如果有人提出解决方案,那将很高兴...

It's not that hard with no additional requirements: 没有其他要求并不难:

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()
}

The error just asks you to add a type to items: 该错误仅要求您为项目添加类型:

let items: Array<Any> = [
    UserItem(name: "Dexter", action: { (item) in print(item.name)}),
    DriverItem(licenseNumber: "1234567890", action: { (item) in print(item.licenseNumber)})
]

Not sure if this won't lead to more errors because I am not sure if you can call a completion block while creating the array. 不知道这是否不会导致更多错误,因为我不确定在创建数组时是否可以调用完成块。


Edit 编辑

I think what you are trying to do is get a call when the variable is called. 我认为您正在尝试做的是在调用变量时获得调用。 The way to do this would be to use the get you already typed but didnt complete, like so: 这样做的方法是使用已经输入但未完成的get ,例如:

var licenseNumber: String {
    get {
        print("doSomething!")
        return self.licenseNumber
    }
}

The array would become something like: 该数组将变为:

let items: Array<Any> = [
    UserItem(name: "Dexter"),
    DriverItem(licenseNumber: "1234567890")
]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM