CHIAMATE DI RETE¶
Cosa imparerò:
- URLSession
- HTTPS
- GET, POST, DELETE
- JSON
- CodingKeys
- Error
In Swift, URLSession è una classe che fornisce un'interfaccia per la comunicazione con server tramite HTTPS. Si tratta di una classe potente e flessibile che consente di eseguire richieste in modo asincrono, sia con closure sia con async/await.
// Definizione dell'URL della richiesta
let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1")!
// Creazione della richiesta
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
// Gestione della risposta
if let error = error {
print("Errore: \(error)")
return
}
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("Errore di risposta del server")
return
}
if let data = data,
let responseData = String(data: data, encoding: .utf8) {
print("Risposta del server:")
print(responseData)
}
}
// Avvio della richiesta
task.resume()
Output
Risposta del server:
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
In questo esempio, viene eseguita una richiesta GET all'URL "https://jsonplaceholder.typicode.com/posts/1" utilizzando URLSession.shared.dataTask(with:). Quando la richiesta viene completata, la closure passata a dataTask(with:) viene chiamata con i dati, la risposta e gli eventuali errori.
HTTPURLResponse viene utilizzato per verificare che la risposta del server sia nell'intervallo di successo (status code 200-299). Se la risposta è valida, i dati vengono stampati sulla console.
URLSession può essere utilizzato anche per eseguire richieste POST, PUT, DELETE, ecc., fornendo i dati del corpo della richiesta, gli header HTTP appropriati e così via.
Utilizzando queryItems, è possibile creare facilmente una stringa di query ben formata e aggiungerla all’URL:
var urlComponents = URLComponents(string: "https://api.github.com/users")!
urlComponents.queryItems = [
"since": "135"
].map { URLQueryItem(name: $0.key, value: $0.value)}
// Creazione dell'URL dall'URLComponents
if let url = urlComponents.url {
print(url)
} else {
print("Impossibile creare l'URL")
}
Output
https://api.github.com/users?since=135
Quando la richiesta GET va a buon fine nella maggior parte dei casi i dati restituiti sono in formato JSON. Utilizzando il metodo JSONDecoder() si possono convertire i dati JSON in un tipo di Swift.
Oltre a convertire i dati in tipi di Swift si può creare il proprio modello e attraverso il protocollo Codable convertire i dati.
// Creazione della richiesta
import Foundation
struct User: Codable {
let login: String
let id: Int
let node_id: String
let avatar_url: String
let gravatar_id: String
let url: String
let html_url: String
let followers_url: String
}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
// Decodifica del JSON in un oggetto User
do {
guard let data = data else { return }
let responseData = try JSONDecoder().decode([User].self, from: data)
print(responseData)
} catch {
print("Errore durante la decodifica del JSON:", error)
}
}
// Avvio della richiesta
task.resume()
Output
[__lldb_expr_149.User(login: "simonjefford", id: 136, nodeId: "MDQ6VXNlcjEzNg==", avatarUrl: "https://avatars.githubusercontent.com/u/136?v=4", gravatarId: "", url: "https://api.github.com/users/simonjefford", htmlUrl: "https://github.com/simonjefford", followersUrl: "https://api.github.com/users/simonjefford/followers"), __lldb_expr_149.User(login: "josh", id: 137, nodeId: "MDQ6VXNlcjEzNw==", avatarUrl: "https://avatars.githubusercontent.com/u/137?v=4", gravatarId: "", url: "https://api.github.com/users/josh", htmlUrl: "https://github.com/josh", followersUrl: "https://api.github.com/users/josh/followers"), ...
]
Le CodingKeys in Swift vengono utilizzate per personalizzare la codifica e la decodifica delle proprietà della struttura. Permettono di mappare i nomi delle chiavi nel JSON ai nomi delle proprietà della struttura durante l'operazione di codifica e decodifica. Devono essere utilizzate quando il nome della proprietà Swift non coincide con la chiave JSON.
struct User2: Codable {
let userID: Int
let login: String
let avatarUrl: String
// Definizione delle chiavi custom per la codifica e la decodifica
enum CodingKeys: String, CodingKey {
case userID = "id"
case username
case avatarUrl = "avatar_url"
}
}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
// Decodifica del JSON in un oggetto User
do {
guard let data = data else { return }
let responseData = try JSONDecoder().decode([User].self, from: data)
print(responseData)
} catch {
print("Errore durante la decodifica del JSON:", error)
}
}
// Avvio della richiesta
task.resume()
Output
[__lldb_expr_159.User2(userID: 140, login: "jwreagor", avatarUrl: "https://avatars.githubusercontent.com/u/140?v=4"), __lldb_expr_159.User2(userID: 141, login: "technomancy", avatarUrl: "https://avatars.githubusercontent.com/u/141?v=4"), __lldb_expr_159.User2(userID: 142, login: "kenphused", avatarUrl: "https://avatars.githubusercontent.com/u/142?v=4"), __lldb_expr_159.User2(userID: 143, login: "rubyist", avatarUrl: "https://avatars.githubusercontent.com/u/143?v=4"), __lldb_expr_159.User2(userID: 144, login: "ogc", avatarUrl: "https://avatars.githubusercontent.com/u/144?v=4"), ...
]
Il tipo Error in Swift è un protocollo che le tipiche implementazioni del linguaggio di errore (come NSError e le Error personalizzate) devono adottare. Possiamo creare un enum personalizzato che adotti il protocollo Error per gestire gli errori in modo più specifico e personalizzato.
// Definizione di un enum personalizzato che rappresenta gli errori di un'applicazione
enum NetworkError: Error {
case invalidURL
case serverError(Int)
case noData
case decodingError
}