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 -
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 -
Swift’s generics do not allow you to leave off placeholder types. You’ll need to fully qualify the parameter as Result<ExampleModelObject, Error>.
However, there’s no reason to rely on Result if your error isn’t typed. You can just use a throwing closure as a parameter. (Which is the same as Swift 5.5’s async throws, but uglier.)
Thanks for the above @jcatterwaul ! That was helpful.
I am still learning swift and so I am struggling to understand what you meant by the above. I thought we usually would use throws only for throwing errors and exceptions.
The Result type’s main purpose is to preserve the specific type of errors. If your failure type is Error itself, then Result doesn’t add any functionality to your code.
Result would be very useful if your failure type was going to be that one in particular:
var result: Result<ExampleModelObject, ExampleModelObject.Error>
But otherwise, these two types convey the same information. That’s because Swift’s throwing closures, get accessors, and functions, do not preserve error type information—only that some type of error might be thrown.
var getExampleModelObject: () throws -> ExampleModelObject
var result: Result<ExampleModelObject, Error>
Successes:
getExampleModelObject = { .init() }
result = .success(.init())
…or failures:
getExampleModelObject = { throw ExampleModelObject.Error() }
result = .failure(ExampleModelObject.Error())
result = .init { throw ExampleModelObject.Error() }
(The last line uses this initializer, which only works with untyped failures.)