Home > Mobile >  Swift - Injecting and storing protocols
Swift - Injecting and storing protocols

Time:10-23

I have a mapper as follows

protocol MapperProtocol {
    associatedtype T
    associatedtype U
    func map(item: T) -> U?
}

And I want to inject it to a class as follows

protocol ParserProtocol {
    associatedtype T
    associatedtype U
    func parse(from: T) -> U?
}

class TrackParser: ParserProtocol {
    typealias T = String
    typealias U = Track
    
    private let mapper: MapperProtocol
    
    init(mapper: MapperProtocol) {
        self.mapper = mapper
    }
    
    func parse(from path: String) -> Track? {
        guard let data = try? Data(contentsOf: URL(filePath: path)) else { return nil }
        return mapper.map(item: data)
    }
}

TrackParser will be initialised from somewhere else so it doesn't need to know the concrete type of the mapper.

When I want to implement it that way I get the following error. Error screenshot Any ideas how to fix it?

CodePudding user response:

Notice that the parse implementation requires that the mapper has T == Data and U == Track, but you haven't specified those constraint anywhere in TrackParser.

We can make T and U the primary associated types of MapperProtocol, so that the same-type requirements can be specified very easily as MapperProtocol<Data, Track>.

protocol MapperProtocol<T, U> { // Notice the "<T, U>"
    associatedtype T
    associatedtype U
    func map(item: T) -> U?
}

Also, starting from Swift 5.7, existential types are required to be prefixed with "any", so you would write:

private let mapper: any MapperProtocol<Data, Track>

init(mapper: any MapperProtocol<Data, Track>) {
    self.mapper = mapper
}
  • Related