简体   繁体   English

面临协议相关类型的问题

[英]Facing an issue with protocol associatedType

I have a list of tableview view data where user can pick one item i'm using ZPPickerDataSource protocol as a datasource, there is no issue at this stage我有一个 tableview 视图数据列表,用户可以在其中选择一个我使用 ZPPickerDataSource 协议作为数据源的项目,在这个阶段没有问题

public protocol ZPPickerDataSource: ZPSearchableDataSource {
    var uuID: String {get}
    var displayString: String {get}
}

In addition the UI has search funcitonality as well, i'm using ZPSearchableDataSource, ZPSearchable for that.此外,UI 还具有搜索功能,为此我正在使用 ZPSearchableDataSource、ZPSearchable。 ZPPickerDataSource protocol confirms to ZPSearchableDataSource. ZPPickerDataSource 协议向 ZPSearchableDataSource 确认。

public protocol ZPSearchableDataSource {
    var displayString: String {get}
}

public protocol ZPSearchable {
    associatedtype dataSourceType: ZPSearchableDataSource
    var searchableItems: [dataSourceType] {get}
    func search(keyword: String) -> [dataSourceType]
}

public extension ZPSearchable {
    func search(keyword: String) -> [dataSourceType] {
        return searchableItems.filter{$0.displayString.contains(keyword)}
    }
}

when i mentions ZPSearchable protocol's当我提到ZPSearchable协议时

typealias dataSourceType = ZPPickerDataSource

i'm getting an error like Your controller does not confirms to protocol ZPSearchable .我收到一个错误,例如Your controller does not Confirms to protocol ZPSearchable

class MyPickerScreen: ZPSearchable {
    
    typealias dataSourceType = ZPPickerDataSource
    var searchableItems: [dataSourceType] {
        return []
    }
    
    var searchResults: [dataSourceType] = []
    func searchItem(namedLike searchQuery: String) {
        searchResults = search(keyword: searchQuery)
    }
    
}

PS: I've tried struct named TestSource as a data source. PS:我尝试过名为TestSource的结构作为数据源。 and i mentioned我提到了

typealias dataSourceType = TestSource 

then the code compiles.然后代码编译。 seems it occurs only with protocol.似乎它只发生在协议中。

public struct TestSource: ZPPickerDataSource {
    public var uuID: String = ""
    public var displayString: String = ""
    public var sampleVar = ""
}

Surprisingly, ZPPickerDataSource does not conform to ZPSearchableDataSource .令人惊讶的是, ZPPickerDataSource不符合ZPSearchableDataSource Only concrete types conform to protocols.只有具体类型符合协议。 Protocols do not conform to protocols.协议不符合协议。 See Hamish's answer in this post for why.请参阅这篇文章中 Hamish 的回答了解原因。

Because of this, your type alias:因此,您的类型别名:

typealias dataSourceType = ZPPickerDataSource

does not satisfy the constraint that dataSourceType must conform to ZPSearchableDataSource , so the associated type requirement is not met, so your type does not conform to the protocol ZPSearchable .不满足dataSourceType必须符合ZPSearchableDataSource的约束,因此不满足关联的类型要求,因此您的类型不符合协议ZPSearchable

You must use a struct/class for the associated type.您必须为关联类型使用结构/类。 You seem to want to be able to use any ZPPickerDataSource .您似乎希望能够使用任何ZPPickerDataSource In that case, you can write a struct that conforms to ZPPickerDataSource , and write a function that converts from any ZPPickerDataSource to your struct:在这种情况下,您可以编写一个符合ZPPickerDataSource的结构,并编写一个 function 将任何ZPPickerDataSource转换为您的结构:

struct AnyZPPickerDataSource: ZPPickerDataSource {
    let wrapped: ZPPickerDataSource
    
    var uuID: String { wrapped.uuID }
    var displayString: String { wrapped.displayString }
    
    init(_ dataSource: ZPPickerDataSource) {
        wrapped = dataSource
    }
}

Then you can do:然后你可以这样做:

class MyPickerScreen: ZPSearchable {
    var searchableItems: [AnyZPPickerDataSource] = []
    
    typealias dataSourceType = AnyZPPickerDataSource
}

Now you can put any kind of ZPPickerDataSource into searchableItems , eg现在您可以将任何类型的ZPPickerDataSource放入searchableItems ,例如

searchableItems.append(AnyZPPickerDataSource(TestSource(...)))

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

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