Как использовать новый тип результата, представленный в swift 5 URLSession? - PullRequest
0 голосов
/ 25 апреля 2019

Swift 5 представляет новый тип Result для обработки результата асинхронной функции.Я хочу знать, как использовать этот новый тип результата для URLSession.

У меня есть следующий код.

func getCategorByAPI()
    {
        //Base Url is from an static variable
        let url = URL(string: URLManager.aPIBaseURL+"category")!
        var request  = URLRequest(url: url)
        request.httpMethod = "GET"
        let boundary = "Boundary-\(UUID().uuidString)"
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

        let task = URLSession.shared.dataTask(with: request as URLRequest) {
            data, response, error in

            if error != nil {
                //print("error=\(error)")
                return
            }

            do {
                let json = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary
                print(json)
            }catch
            {
                print(error)
            }

        }

        task.resume()
    }

Как мне переписать эту функцию, используя swift5 Тип результата?

1 Ответ

0 голосов
/ 27 апреля 2019

Вы хотите создать enum, который указывает возможные случаи в вашем результате (например, успех или неудача). Затем вы добавляете завершение к вашему getCategorByAPI() методу типа Result<Data, Error>. Оттуда, в сеансе url, вы будете вызывать обработчик завершения, передавая либо data на .success, либо error на .failure.

Вы также можете делать классные вещи, такие как переопределение Result get() метода и расширение Result для декодирования ваших данных: D

Проверьте это:

enum Result<Success, Error: Swift.Error> {
    case success(Success)
    case failure(Error)
}

// override the Result.get() method
extension Result {
    func get() throws -> Success {
        switch self {
        case .success(let value):
            return value
        case .failure(let error):
            throw error
        }
    }
}

// use generics - this is where you can decode your data
extension Result where Success == Data {
    func decoded<T: Decodable>(using decoder: JSONDecoder = .init()) throws -> T {
        let data = try get()
        return try decoder.decode(T.self, from: data)
    }
}


func getCategorByAPI(completion: (Result<Data, Error>) -> Void)
{
    // You might want to stick this into another method
    let url = URL(string: URLManager.aPIBaseURL+"category")!
    var request  = URLRequest(url: url)
    request.httpMethod = "GET"
    let boundary = "Boundary-\(UUID().uuidString)"
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

    URLSession.shared.dataTask(with: request as URLRequest) {
        data, response, error in

        if error != nil {
            completion(.failure(error))
            return
        }

        if !(200...299).contains(httpResponse.statusCode) && !(httpResponse.statusCode == 304) {
            let httpError = // ... convert httpResponse.statusCode into a more readable error
                completion(.failure(httpError))
        }

        if let data = data {
            completion(.success(data))
        }
        }.resume()
}

Я не проверял вышеизложенное, но что-то подобное реализовано в текущем проекте. Вот несколько статей, которые я прочитал, чтобы узнать о том, как реализовать:

https://www.hackingwithswift.com/articles/161/how-to-use-result-in-swift
https://medium.com/@pavlepesic/how-to-use-swift-5-result-with-codable-protocol-824c9a951af9

...