0

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

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. ZPPickerDataSource protocol confirms to 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

typealias dataSourceType = ZPPickerDataSource

i'm getting an error like 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)
    }
    
}

P.S: I've tried struct named TestSource as a data source. 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 = ""
}

1 Answers1

0

Surprisingly, ZPPickerDataSource does not conform to ZPSearchableDataSource. Only concrete types conform to protocols. Protocols do not conform to protocols. See Hamish's answer in this post for why.

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.

You must use a struct/class for the associated type. You seem to want to be able to use any 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:

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, e.g.

searchableItems.append(AnyZPPickerDataSource(TestSource(...)))
Sweeper
  • 213,210
  • 22
  • 193
  • 313