Iniziare con Alamofire

Per iniziare a integrare Alamofire nel tuo progetto iOS, puoi aggiungere la libreria utilizzando Swift Package Manager, CocoaPods o Carthage. Swift Package Manager è l'approccio consigliato in quanto è stato costruito in Xcode. Aggiungi il pacchetto Alamofire navigando in File] → Add Packages

import Alamofire

L’alias di Alamofire fornisce un comodo punto di ingresso per tutte le operazioni HTTP comuni. Sotto il cofano, utilizza Apple ma astratti via caldaia come la gestione della coda, la codifica dei parametri e la validazione della risposta. Questo consente di concentrarsi sulla logica aziendale piuttosto che su come creare un impianto di rete.

Eseguire richieste GET

L'operazione più comune è quella di ottenere dati da un punto di vista RESTful. Alamofire rende le richieste GET concise e leggibili. L'esempio seguente recupera un elenco di utenti da un'API ipotetica:

AF.request("https://api.example.com/users")
 .validate()
 .responseDecodable(of: [User].self) { response in
 switch response.result {
 case .success(let users):
 print("Fetched \(users.count) users")
 case .failure(let error):
 print("Request failed with error: \(error)")
 }
 }

Si noti l'uso di , che sfrutta il protocollo di Swift [] per analizzare automaticamente JSON in oggetti di modello. Definire un [] struttura che si conformi a [] (o ]]]).

Aggiungere parametri di query e intestazioni

Molte API REST richiedono parametri di query o intestazioni HTTP personalizzate. Alamofire accetta parametri come dizionario e gestisce la codifica automaticamente per le richieste GET (i parametri sono allegati all'URL).

let parameters: Parameters = ["page": 1, "limit": 20]
let headers: HTTPHeaders = [
 "Authorization": "Bearer YOUR_TOKEN",
 "Accept": "application/json"
]

AF.request("https://api.example.com/users",
 parameters: parameters,
 headers: headers)
 .validate()
 .responseDecodable(of: [User].self) { response in
 // handle response
 }

Alamofire codifica automaticamente i parametri e li attacca all'URL di richiesta. Per codifica personalizzata, è possibile specificare un'istanza esplicita , come ].

Validazione della risposta

Il metodo verifica automaticamente i codici di stato HTTP nella gamma 200–299 e rifiuta le risposte con un tipo di contenuto non accessibile. È inoltre possibile aggiungere criteri di validazione personalizzati. Ad esempio, per accettare solo 200 e 201 codici di stato:

.validate(statusCode: [200, 201])

I guasti di convalida vengono segnalati come errori nel gestore di risposta, permettendo di implementare una gestione coerente degli errori durante l'applicazione.

Invio di dati POST

La creazione o l'aggiornamento di risorse richiede tipicamente una richiesta POST con un corpo di richiesta. Alamofire supporta più strategie di codifica, con [] essere il più comune per le API REST. L'esempio seguente invia un nuovo oggetto utente al server:

let newUser: [String: Any] = [
 "name": "Jane Doe",
 "email": "[email protected]"
]

AF.request("https://api.example.com/users",
 method: .post,
 parameters: newUser,
 encoding: JSONEncoding.default)
 .validate()
 .responseDecodable(of: User.self) { response in
 switch response.result {
 case .success(let createdUser):
 print("User created: \(createdUser)")
 case .failure(let error):
 print("Error creating user: \(error)")
 }
 }

Se l'API si aspetta che i dati del modulo codificato URL (ad esempio, per lo scambio di token OAuth), utilizzino []. Per i file caricati o i dati misti, Alamofire fornisce ] che costruisce una richiesta multipart. Esempio:

AF.upload(multipartFormData: { multipartFormData in
 multipartFormData.append(Data("Jane Doe".utf8), withName: "name")
 multipartFormData.append(imageData, withName: "avatar", fileName: "avatar.jpg", mimeType: "image/jpeg")
}, to: "https://api.example.com/users")
 .validate()
 .responseDecodable(of: User.self) { response in
 // handle response
 }

Lavorare con altri metodi HTTP

Le API RESTful richiedono spesso operazioni PUT (aggiornamento completo), PATCH (aggiornamento parziale), e DELETE (removal). Alamofire gestisce queste operazioni con lo stesso metodo []; semplicemente cambia il parametro .

PUT e PATCH

Per aggiornare una risorsa esistente, utilizzare o [. L'organismo di richiesta contiene i campi aggiornati:

let updatedFields: [String: Any] = ["name": "Jane Smith"]
AF.request("https://api.example.com/users/123",
 method: .patch,
 parameters: updatedFields,
 encoding: JSONEncoding.default)
 .validate()
 .responseDecodable(of: User.self) { response in
 // handle updated user
 }

DELETE

La cancellazione di una risorsa non richiede in genere alcun corpo di richiesta. La risposta potrebbe essere vuota o restituire un messaggio di conferma:

AF.request("https://api.example.com/users/123",
 method: .delete)
 .validate()
 .response { response in
 if let error = response.error {
 print("Delete failed: \(error)")
 } else {
 print("User deleted successfully")
 }
 }

Controllare sempre la documentazione API per i codici di stato previsti (ad esempio, 204 No Content).

Gestione e monitoraggio di rete degli errori avanzati

Alamofire segnala gli errori attraverso il tipo , che differenzia tra errori di rete (timeout, no Connection), errori del server (cattivo codice di stato), e guasti di serializzazione (invalid JSON).

switch response.result {
case .success(let value):
 // handle success
case .failure(let error):
 if let afError = error.asAFError {
 switch afError {
 case .sessionTaskFailed(let sessionError):
 print("Network issue: \(sessionError.localizedDescription)")
 case .responseValidationFailed(let reason):
 print("Validation failed: \(reason)")
 default:
 print("Other Alamofire error: \(afError.localizedDescription)")
 }
 }
}

Reachability della rete

Prima di effettuare richieste, è possibile verificare la disponibilità della rete. Alamofire [] monitora i cambiamenti di connettività.

let reachabilityManager = NetworkReachabilityManager()
reachabilityManager?.startListening { status in
 switch status {
 case .notReachable:
 print("Network is not reachable")
 case .reachable(.cellular):
 print("Connected via cellular")
 case .reachable(.ethernetOrWiFi):
 print("Connected via WiFi")
 case .unknown:
 print("Unknown status")
 }
}

Per modelli più avanzati, considerare la combinazione di raggiungibilità con un meccanismo di riprova, come la riprova delle richieste fallite quando la connettività viene ripristinata.

Migliori Pratiche per la produzione-Ready Networking

Seguendo i modelli consolidati manterrà il vostro livello di rete manutenevole, sicuro e performante.

1. Adottare modelli di codable

Definire sempre i tipi Swift che si conformi a (o ]) per la parasing di risposta. Questo elimina la manipolazione manuale JSON e riduce i bug. Usa [ o il livello inferiore ] se avete bisogno di contenuti dinamici.

2. Autenticazione e gestione dei gettoni più sicuri

Non distruggi mai le chiavi API o i gettoni. Conservare i valori sensibili nella Portachiavi e allegare le richieste tramite l'intestazione [. Per i flussi di OAuth, implementare un intercettatore di aggiornamento di token. Il protocollo di Alamofire consente di riprovare automaticamente le richieste dopo aver ottenuto un nuovo token.

class AuthInterceptor: RequestInterceptor {
 func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
 var request = urlRequest
 request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
 completion(.success(request))
 }

 func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
 // Check if error is 401, refresh token, then retry
 completion(.retryWithDelay(1.0))
 }
}

3. Concorrenza con asinc/aspettativa

Alamofire 5 supporta pienamente il modello di concurrency di Swift. Utilizzare le versioni dei metodi di richiesta per scrivere codice lineare e pulito:

do {
 let users = try await AF.request("https://api.example.com/users")
 .serializingDecodable([User].self)
 .value
 print("Users: \(users)")
} catch {
 print("Error: \(error)")
}

Combinare questo con una convalutazione strutturata (gruppi di tabulazione, attori) per gestire più richieste ed evitare l'inferno di callback.

4. Caching di implementazione

Per ridurre le chiamate di rete e migliorare il supporto offline, configurare le politiche di caching. Alamofire rispetta il [ (ad esempio ]]]. È inoltre possibile utilizzare un personalizzato con una capacità di disco appropriata:

let cache = URLCache(memoryCapacity: 10 * 1024 * 1024,
 diskCapacity: 50 * 1024 * 1024,
 diskPath: "networking_cache")
let session = Session(configuration: URLSessionConfiguration.default)
session.sessionConfiguration.urlCache = cache

5. Testare il livello di rete

Alamofire []]] può essere iniettato con un protocollo di mock che restituisce risposte predefinite. Considerate l'utilizzo di librerie come o l'astrazione incorporata .

6. Utilizzare un Gestore di rete centralizzato

Creare una classe che configura un'istanza [] con URL di base, intestazioni, intercettatori e cache condivisa.

class APIClient {
 static let shared = APIClient()
 private let session: Session

 private init() {
 let config = URLSessionConfiguration.default
 config.timeoutIntervalForRequest = 30
 config.urlCache = URLCache.shared
 session = Session(configuration: config, interceptor: AuthInterceptor())
 }

 func fetchUsers() async throws -> [User] {
 return try await session.request("\(baseURL)/users")
 .serializingDecodable([User].self)
 .value
 }
}

Per una comprensione completa dei modelli di rete, fare riferimento al Alamofire Advanced Documentazione di utilizzo[]. Inoltre, il Estratto di API REST a restfulapi.net[] offre preziose informazioni sulla progettazione di API robuste.

Seguendo queste linee guida e sfruttando l’API espressiva di Alamofire, è possibile costruire uno strato di rete potente e facile da mantenere. La libreria astratti molti degli aspetti noiosi del caricamento dell’URL, dando il pieno controllo quando ne hai bisogno.