udacity / ios-nd-networking

Resources for Udacity's iOS Networking with Swift course.
MIT License
172 stars 88 forks source link

Use Swift 5's Result type for completion handlers #17

Open OwenLaRosa opened 5 years ago

OwenLaRosa commented 5 years ago

When we call dataTask(with:), we receive a completion handler with three values: data, response, and error. Similarly, the completion handlers we provide in our helper methods, return either the generic ResponseType or an Error - both optional so that if one has a value, the other one is nil.

This works, but leads to excessive nil-checking at the call site. Because there's only two cases (success, in which we receive data, and failure, in which we receive an error), a common pattern is to use an enum with associated values as the single value passed back by the completion handler. This is called the Result type, and was actually added to Swift 5 to make for cleaner completion handlers.

For example, if we use the Result type in the taskForGETRequest method, then the method signature would look like this.

class func taskForGETRequest<ResponseType: Decodable>(url: URL, responseType: ResponseType.Type, completion: @escaping (Result<ResponseType, Error>) -> Void) -> URLSessionDataTask { ... }

Now, the ResponseType and Error are not optional and can never be nil. When we want to call the completion handler, because Result is an enumwe either pass in an instance of the response type to thesuccesscase, or an error into thefailurecase. Wrapping all our completion handlers in aResult` type eliminates the need for nil-checking, and keeps our code cleaner and easier to understand.

For more information on the Result type, refer to the documentation and the Swift Evolution proposal.