learner2010
learner2010

Reputation: 4167

Using Generic parameter in closure

I have a function that makes a service call to fetch data, uses JSONDecoder to decode the JSON response into a model object and then return that object as part of a parameter in the completion block provided to the function. In the object, I am actually using the Result object. Here is the code -

static func fetchData(_ completion: @escaping (Result<ExampleModelObject, Error>) -> Void)

I am trying to make this function generic, where it can accept the url it needs to call as one parameter and the Model object as another parameter and so I modified it to this -

static func fetchData <T: Decodable>(urlString: String, _ completion: @escaping (Result<T, Error>) -> Void)

This is the code where I use jsondecoder -

let parsedJSON = try jsonDecoder.decode(T.self, from: data)
            completion(.success(parsedJSON))

Here is how I am trying to call this function from another class -

DataRetriever. fetchData(urlString: dataURLString) { (result: ExampleModelObject) in

However, I am getting 2 errors during compilation -

  1. Cannot convert value of type '(ExampleModelObject) -> Void' to expected argument type '(Result<_, Error>) -> Void'
  2. Generic parameter 'T' could not be inferred

Would anyone please be able to help me with how I can fix these errors?

Upvotes: 0

Views: 830

Answers (3)

matsotaa
matsotaa

Reputation: 123

try to

 fetchData(urlString: "") { (result: Result<ExampleModelObject, Error>) in
            
 }

or use two completion blocks like so:

 func fetchData<T: Decodable>(urlString: String, success: @escaping(T) -> Void, failure: @escaping(Error) -> Void) {
    
 }

execution:

fetchData(urlString: "") { (model: ExampleModelObject) in
            
} failure: { error in
            
}

Upvotes: 3

Johannes
Johannes

Reputation: 586

With an additional parameter you can help the combiler to recognise the type.

If you define the function in this way, it is no longer necessary to specify the type in the closure parameter.

static func fetchData <T: Decodable>(type: T.Type, urlString: String, _ completion: @escaping (Result<T, Error>) -> Void)

The call then looks like this:

DataRetriever.fetchData(type: ExampleModelObject.self, urlString: dataURLString) { result in }

Upvotes: 1

vadian
vadian

Reputation: 285072

You have to specify the full type

DataRetriever.fetchData(urlString: dataURLString) { (result: Result<ExampleModelObject,Error>) in

Upvotes: 2

Related Questions