Skip to content

Instantly share code, notes, and snippets.

@perlguy99
Created December 12, 2019 14:57
Show Gist options
  • Save perlguy99/06189d9ce7e0459bd8334e3a8f498953 to your computer and use it in GitHub Desktop.
Save perlguy99/06189d9ce7e0459bd8334e3a8f498953 to your computer and use it in GitHub Desktop.
Swift Result Type

Swift Result

Thanks to Paul Hudson, Hacking with Swift

//
//  ContentView.swift
//  ResultTypeTest
//
//  Created by Michalski (US), James B on 12/12/19.
//  Copyright © 2019 Perlguy, Inc. All rights reserved.
//

import SwiftUI

enum NetworkError: Error {
    case badURL, requestFailed, unknown
}

struct ContentView: View {
    var body: some View {
        // Original
//        Text("Hello, World!")
//            .onAppear {
//                let url = URL(string: "https://www.apple.com")!
//                URLSession.shared.dataTask(with: url) { data, response, error in
//                    if data != nil {
//                        print("We got data!")
//                    }
//                    else if let error = error {
//                        print(error.localizedDescription)
//                    }
//                }.resume()
//        }
        
        // New, improved version
        Text("Hello, World!")
            .onAppear {
                self.fetchData4(from: "https://www.apple.com") { result in
                    switch result {
                    case .success(let str):
                        print(str)
                    case .failure(let error):
                        switch error {
                        case .badURL:
                            print("Bad URL")
                        case .requestFailed:
                            print("Request Failed")
                        case .unknown:
                            print("Unknown error")
                        }
                    }
                }
        }
    }
    
    // 1: Still a blocking call
    func fetchData1(from urlString: String) -> Result<String, NetworkError> {
        .failure(.badURL)
    }
    
    // 2: Now with a completion closure
    func fetchData2(from urlString: String, completion: (Result<String, NetworkError>) -> Void) {
        completion(.failure(.badURL))
    }
    
    
    // 3: Now @escaping so we can run asynchronously
    func fetchData3(from urlString: String, completion: @escaping (Result<String, NetworkError>) -> Void) {
        DispatchQueue.main.async {
            completion(.failure(.badURL))
        }
    }
    
    
    // 4
    func fetchData4(from urlString: String, completion: @escaping (Result<String, NetworkError>) -> Void) {
        // check the URL is OK, otherwise return with a failure
        guard let url = URL(string: urlString) else {
            completion(.failure(.badURL))
            return
        }
        
        URLSession.shared.dataTask(with: url) { data, response, error in
            // the task has completed - push our work back to the main thread
            DispatchQueue.main.async {
                if let data = data {
                    // success: convert the data to a string and send it back
                    let stringData = String(decoding: data, as: UTF8.self)
                    completion(.success(stringData))
                }
                else if error != nil {
                    // any sort of network failure
                    completion(.failure(.requestFailed))
                }
                else {
                    // this shouldn't be possible, yet here we are
                    completion(.failure(.unknown))
                }
            }
        }.resume()
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment