Começando com o Alamofire

Para começar a integrar o Alamofire no seu projecto iOS, pode adicionar a biblioteca usando o Swift Package Manager, o CocoaPods ou o Carthage. O Swift Package Manager é a abordagem recomendada, dado que é incorporado no Xcode. Adicione o pacote Alamofire navegando para File[Adicionar Pacotes[] e introduzindo o URL do repositório . Especificar a versão 5.0.0 ou posterior. Alternativamente, se utilizar o CocoaPods, adicione ao seu Podfile e execute [. Uma vez que a dependência estiver integrada, importe o Alamofire em qualquer ficheiro Swift onde necessite de funcionalidade de rede:

import Alamofire

O alias do Alamofire fornece um ponto de entrada conveniente para todas as operações HTTP comuns. Sob o capô, ele usa o da Apple, mas abstrai a caldeira como gerenciamento de filas, codificação de parâmetros e validação de respostas. Isso permite que você se concentre na lógica de negócios em vez de encanamento de rede. Para mais detalhes sobre a camada de rede subjacente, consulte A documentação URLSession da Apple.

Realizando Pedidos de GET

A obtenção de dados de um endpoint RESTful é a operação mais comum. O Alamofire torna as requisições GET concisas e legíveis. O exemplo seguinte recupera uma lista de usuários de uma API hipotética:

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)")
 }
 }

Observe o uso de , que alavanca o protocolo de Swift para processar automaticamente o JSON em objetos de modelo. Defina uma estrutura que se conforme com [] (ou ). Esta abordagem elimina a serialização manual do JSON e melhora a segurança do tipo.

Adicionando Parâmetros e Cabeçalhos de Consulta

Muitas APIs REST requerem parâmetros de consulta ou cabeçalhos HTTP personalizados. O Alamofire aceita parâmetros como um dicionário e lida automaticamente com codificação para requisições GET (parâmetros são adicionados ao URL). Os cabeçalhos são adicionados através do parâmetro :

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 os parâmetros e os liga ao URL da solicitação. Para codificação personalizada, você pode especificar uma instância explícita , como ].

Validação da Resposta

O método verifica automaticamente os códigos de estado HTTP na gama 200–299 e rejeita as respostas com um tipo de conteúdo não aceitável. Também pode adicionar critérios de validação personalizados. Por exemplo, para aceitar apenas 200 e 201 códigos de estado:

.validate(statusCode: [200, 201])

Falhas de validação são relatadas como erros no manipulador de resposta, permitindo que você implemente o manuseio consistente de erros durante toda a aplicação.

Enviando Dados POST

Criar ou atualizar recursos normalmente requer uma solicitação POST com um corpo de solicitação. O Alamofire suporta múltiplas estratégias de codificação, sendo a mais comum para APIs REST. O exemplo a seguir envia um novo objeto de usuário para o servidor:

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 a API esperar dados de formulários codificados por URL (por exemplo, para troca de tokens de OAuth), use em vez disso. Para uploads de arquivos ou dados mistos, o Alamofire fornece que constrói uma solicitação multiparte. Exemplo:

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
 }

Trabalhando com Outros Métodos HTTP

APIs RESTful muitas vezes requerem PUT (atualização completa), PATCH (atualização parcial) e operações DELETE (remoção). Alamofire lida com essas operações com o mesmo método ; simplesmente mude o parâmetro .

PUT E PATCH

Para atualizar um recurso existente, use ou . O corpo de solicitação contém os campos atualizados:

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

A remoção de um recurso normalmente não requer nenhum corpo de solicitação. A resposta pode estar vazia ou retornar uma mensagem de confirmação:

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")
 }
 }

Verifique sempre a documentação da API para códigos de status esperados (por exemplo, 204 Nenhum Conteúdo).

Manuseamento avançado de erros e monitoramento de rede

O tratamento de erros robustos é fundamental para uma experiência de usuário perfeita. O Alamofire reporta erros através do tipo , que diferencia erros de rede (tempo limite, sem conexão), erros de servidor (código de estado ruim) e falhas de serialização (inválida JSON). Você pode inspecionar o erro para fornecer feedback específico:

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)")
 }
 }
}

Alcance da rede

Antes de fazer pedidos, você pode querer verificar a disponibilidade da rede. Alamofire monitora as alterações de conectividade. Comece a monitorar precocemente no seu ciclo de vida do aplicativo:

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")
 }
}

Use isto para informar o usuário ou adiar as solicitações. Para padrões mais avançados, considere combinar a acessibilidade com um mecanismo de reexperimentação, como retentar solicitações falhadas quando a conectividade for restaurada.

Melhores práticas para a produção-prontos em rede

Seguindo padrões estabelecidos, manterá sua camada de rede sustentável, segura e performante.

1. Adote modelos codáveis

Defina sempre os tipos Swift que estão em conformidade com (ou ]]) para análise de resposta. Isto elimina a manipulação manual do JSON e reduz os erros. Use ou o nível inferior se precisar de conteúdo dinâmico. O guia de codificação da Apple cobre o mapeamento avançado com chaves personalizadas.

2. Autenticação mais segura e gerenciamento de token

Nunca são necessárias chaves ou tokens de API de código rígido. Armazene valores sensíveis no Keychain e as anexe a requisições através do cabeçalho . Para fluxos de OAuth, implemente um interceptador de atualização de tokens. O protocolo do Alamofire] permite que você tente refazer automaticamente as requisições após obter um novo token. esqueleto de exemplo:

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. Concorrencial com assincronia/aguarda

Alamofire 5 suporta totalmente o modelo de concorrência da Swift. Use as versões dos métodos de solicitação para escrever código linear mais limpo:

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

Combine isso com a concorrência estruturada (grupos de tarefas, atores) para gerenciar várias solicitações e evitar o inferno de retorno de chamadas.

4. Implementar o Caching

Para reduzir as chamadas de rede e melhorar o suporte offline, configure as políticas de cache. O Alamofire respeita o (por exemplo, ]). Você também pode usar um personalizado com uma capacidade de disco adequada:

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. Teste sua camada de rede

Escreva testes unitários para seus clientes API usando dados simulados. A abstração de Alamofire pode ser injetada com um protocolo simulado que retorna respostas pré-definidas. Considere usar bibliotecas como ou a abstração incorporada . Testando garante que seu tratamento de erros e lógica de análise estão corretos sem atingir os objetivos reais.

6. Use um gerenciador de rede centralizado

Criar uma única classe que configure uma instância com URL base, cabeçalhos, interceptores e uma cache compartilhada. Isto evita a duplicação e torna fácil trocar políticas ou zombar de toda a camada. Exemplo:

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
 }
}

Para uma compreensão abrangente dos padrões de rede, consulte o Alamofire Advanced Usage documentation. Além disso, o tutorial REST API em restfulapi.net[ oferece insights valiosos sobre o projeto de APIs robustas.

Seguindo essas diretrizes e aproveitando a expressiva API do Alamofire, você pode construir uma camada de rede que é poderosa e fácil de manter. A biblioteca abstrai muitos dos aspectos tediosos do carregamento de URL, dando-lhe controle total quando você precisar.