Una classe Swift per un client WebService

Una breve classe da cui prendere spunto:


// MARK: - WebServiceError

public enum WebServiceError: Error {
    case badURL
    case error
    case nodata
    case jsonError
    // ...
}

// MARK: - WebService

public class WebService {
    let baseUrl: String
    public enum HttpMethod: String {
        case GET
        case POST
        case PUT
        case TRACE
        case DELETE
    }

    public init?(baseUrl: String) {
        guard !baseUrl.isEmpty else {
            return nil
        }
        if baseUrl.last! == "/" {
            self.baseUrl = baseUrl
        } else {
            self.baseUrl = baseUrl+"/"
        }
    }

    public func request<T>(with httpMethod: HttpMethod = .GET,
                    of _: T.Type,
                    on path: String, _ completion: @escaping (Result<T, WebServiceError>) -> Void) -> Void where T: Codable
    {
        guard let url = URL(string: baseUrl + path) else {
            completion(.failure(.badURL))
            return
        }
        var request = URLRequest(url: url)
        request.httpMethod = httpMethod.rawValue
        request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")

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

            var result: Result<T, WebServiceError>

            defer {
                completion(result)
            }

            guard error == nil else {
                result = .failure(.error)
                return
            }

            guard let data = data else {
                result = .failure(.nodata)
                return
            }

            let decoder = JSONDecoder()
            decoder.dateDecodingStrategy = .iso8601

            guard let response = try? decoder.decode(T.self, from: data) else {
                result = .failure(.jsonError)
                return
            }
            result = .success(response)
        }

        task.resume()
    }
}

Client REST in Swift per app su iOS e macOS

Quando realizziamo un app dobbiamo spesso consentirle di comunicare con un server per inviare o ricevere messaggi.

Spesso questa comunicazione avviene attraverso una web service, cioè (generalizzando e semplificando molto) un servizio reso disponibile attraverso una rete distribuita che fa uso del protocollo HTTP per il trasporto dei messaggi.

Cos’è REST e cosa c’entra con la comunicazione della nostra app?

REST sta per REpresesentational State Transfer ed è un insieme di principi architetturali per la progettazione di un sistema di ipertesto distribuiti. Sarebbe interessante, ma non voglio dilungarmi al riguardo in questo articolo. Per adesso ci basta sapere che vengono definiti dei vincoli che riguardano la comunicazione di un client con un server. Questi vincoli stabiliscono che la comunicazione deve essere costituita da un’interfaccia uniforme, che il server non deve memorizzare nessun contesto tra una comunicazione e l’altra (stateless), …

Un concetto fondamentale è l’esistenza delle risorse a cui si può accedere tramite un identificatore globale (URI: Uniform Resource Interface). Il client deve solo sapere qual è l’URI per accedere alla risorsa, gli eventuali parametri (ID della risorsa ad esempio) e il formato di rappresentazione che generalmente (e in questo articolo) è il JSON (guarda come è semplice lavorare in JSON con Swift 4).

(Se vuoi una classe Swift pronta come base per un client: https://mirchaemanuel.com/una-classe-swift-per-un-client-webservice/

Continua a leggere Client REST in Swift per app su iOS e macOS