Ruslan
Ruslan

Reputation: 45

Error trying to return protocol associated type from method

I need to search for entities (photos, albums, etc) using unsplash.com search APIs. In order to reach reusability and not having to create a new function every time I need to search for a new entity I created a protocol:

protocol SearchApiResource {

    associatedtype ModelType: Decodable

    var methodPath: String { get }

    var searchTerm: String { get set }

    var pageNumber: Int { get set }

    var parameters: [String: String] { get }

    var url: URL { get }
}

And a structure conforming to that protocol:

struct SearchPhotoResource: SearchApiResource {

    typealias ModelType = Photo
    
    var methodPath = "/search/photos"
    
    var searchTerm = String()
    
    var pageNumber = Int()
    
    let itemsPerPage = 30
    
    let accessKey = "93e0a185df414cc1d0351dc2238627b7e5af3a64bb228244bc925346485f1f44"
    
    var parameters: [String: String] {
        var params = [String: String]()
        params["query"] = searchTerm
        params["page"] = String(pageNumber)
        params["per_page"] = String(itemsPerPage)
        params["client_id"] = accessKey
        return params
    }
    
    var url: URL {
        var components = URLComponents()
        components.scheme = "https"
        components.host = "api.unsplash.com"
        components.path = methodPath
        components.queryItems = parameters.map {URLQueryItem(name: $0, value: $1)}
        return components.url!
    }
    
}

Now I want to create a function that will accept an struct or class conforming to SearchApiResource protocol:

func searchForItem(resource: SearchApiResource, searchTerm: String, pageNumber: Int, completion: @escaping (SearchApiResource.ModelType) -> Void ) {
}

But I receive an error:

"Associated type 'ModelType' can only be used with a concrete type or generic parameter base"

How to fix an error and what am I doing wrong?

Upvotes: 1

Views: 43

Answers (1)

Sweeper
Sweeper

Reputation: 273805

Just do what the error says - use SearchApiResource as a generic parameter base.

func searchForItem<T: SearchApiResource>(resource: T, searchTerm: String, pageNumber: Int, completion: @escaping (T.ModelType) -> Void ) {
}

Upvotes: 3

Related Questions