Network Requests in Swift Using the Result Type and Generics

How you can leverage Swift’s Result type combined with generics when making network requests

Primoz Cimerman
Nov 26, 2019 · 3 min read
Photo by Anna Gru on Unsplash

The Result is an enum with two cases: success and failure, both of which are implemented using generics.

Success can be anything, but failure must conform to the Error protocol. (You can implement your own error types, or just use Swift’s Error.)

Introduction of the Result type in Swift gives us a chance to handle the results of asynchronous functions in a cleaner and safer way.

Let’s see the benefits of using Result vs. not using it on a simple network request example that uses generic types for both success and error values.

We’ll start by implementing a RequestError type and creating a NetworkService class that has two functions.

They are both responsible for making a URL request, the difference being that one uses Result for handling the result (pun intended), while the other one uses the plain old completion handler.

As you can see, using Result makes the code easier to read.

On top of that, a completion handler approach is bug-prone because its success and error values are both Optional types, therefore, the following two examples would be valid (as far as the compiler is concerned), leading us to a weird state:

These kinds of bugs shouldn’t happen using our simple network request implementation, but as the code gets more complex (or is used differently) there’s certainly an option to make an error.

We can draw similar conclusions about code clarity and safety if we take a look at both functions when they are used by NetworkService consumers.

Not only is the function that uses Result much cleaner, but if there’s a bug in the function that uses the completion handler approach, it has the potential to completely mess the flow of our app.

For example, by leaving the app in a stuck state (when none of the values are present), or proceeding with the flow while simultaneously showing an error alert (when both of the values are present).


Result Type With Generics

The above network request example only supports String values in case of success. But what if we want to support other value types, as well? Generics to the rescue!

First, we need to modify the makeUrlReqeust function to support generic types.

Then, we must modify our consumer-side code.

Using Result with a generic type inside of a closure requires that the generic type is specified when creating the closure, otherwise, the compiler will throw the following error:

Finally, we need to change the decodedData function to support decoding to other values besides a String (check one possible implementation below), and voilà — you can now use any value you want!


Conclusion

Even though the example used in this article is a simple one, it clearly demonstrates how the Result type can make our lives easier when we are handling the responses of network requests.

Thanks for reading and please let me know if you have any comments or questions!

Better Programming

Advice for programmers.

Primoz Cimerman

Written by

iOS engineer | Apple enthusiast

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade