Alamofire 网络库:Swift 优雅 HTTP 客户端

FreeGuideOnline 最新 2026-06-17

Alamofire 网络库:Swift 优雅 HTTP 客户端

什么是 Alamofire?

Alamofire 是一个用 Swift 编写的 HTTP 网络库,由 Alamofire 软件基金会维护。它的命名源自阿拉莫之火(Alamo Fire),寓意强大而炽热的性能。Alamofire 提供了极其简洁的链式调用接口,能够大幅简化 iOS、macOS、tvOS 和 watchOS 应用中的网络请求处理。

核心特点:

  • 链式响应处理:使用闭包和 Combine/async/await 风格处理异步操作。
  • 请求与响应序列化:自动将 JSON、Property List、XML 等数据解码为模型。
  • URL / JSON 参数编码:内置多种编码器,轻松构建 GET、POST 请求。
  • 上传与下载:支持文件、数据流和多部分表单上传,以及带进度、断点续传的下载。
  • 认证与安全:原生支持 HTTP 基础认证、Bearer Token、SSL Pinning 等。
  • 网络可达性:提供 NetworkReachabilityManager 监听网络状态变化。
  • 拦截器与适配器:可在请求发送前后插入自定义逻辑,例如刷新 Token、全局错误处理。

安装 Alamofire

推荐使用 Swift Package Manager(SPM)集成。

通过 Xcode 添加

  1. 在 Xcode 中选择 File → Add Packages…
  2. 在搜索栏输入 https://github.com/Alamofire/Alamofire.git
  3. 依赖规则选择 Up to Next Major Version,输入 5.8.0 或更高版本(截止 2025 年推荐使用 5.x)
  4. 点击 Add Package

通过 Package.swift 添加

dependencies: [
    .package(url: "https://github.com/Alamofire/Alamofire.git", .upToNextMajor(from: "5.8.0"))
]

CocoaPods 和 Carthage 仍被支持,但最佳实践推荐 SPM。

快速入门:第一个请求

import Alamofire

AF.request("https://httpbin.org/get").response { response in
    debugPrint(response)
}

AF 是 Alamofire 提供的全局会话单例,足以覆盖大多数需求。你也可以创建自定义 Session 实例来实现更精细的控制。

处理 JSON 响应

AF.request("https://api.example.com/users")
    .validate()                          // 自动检查状态码 200..<300
    .responseDecodable(of: [User].self) { response in
        switch response.result {
        case .success(let users):
            print("获取到 \(users.count) 个用户")
        case .failure(let error):
            print("请求失败: \(error)")
        }
    }

配合 Codable 模型,Alamofire 可以直接将响应解析为 Swift 对象。

构建各种请求

GET 请求与查询参数

let parameters = ["page": "1", "limit": "20"]
AF.request("https://api.example.com/items", parameters: parameters)
    .responseDecodable(of: [Item].self) { response in
        // 处理结果
    }

默认使用 URLEncoding.default 编码参数,适用于 GET 和 DELETE 请求。

POST 请求与 JSON 参数

struct LoginRequest: Encodable {
    let email: String
    let password: String
}

let login = LoginRequest(email: "user@example.com", password: "secret")
AF.request("https://api.example.com/login",
           method: .post,
           parameters: login,
           encoder: JSONParameterEncoder.default)
    .responseDecodable(of: AuthToken.self) { response in
        // 处理令牌
    }

使用 JSONParameterEncoder 将请求体序列化为 JSON,并自动设置 Content-Type: application/json

设置自定义请求头

let headers: HTTPHeaders = [
    "Authorization": "Bearer your_token",
    "Accept": "application/json"
]

AF.request("https://api.example.com/profile", headers: headers)
    .responseDecodable(of: Profile.self) { response in
        // ...
    }

上传文件

通过文件 URL 上传

let fileURL = Bundle.main.url(forResource: "image", withExtension: "png")!

AF.upload(fileURL, to: "https://httpbin.org/post")
    .uploadProgress { progress in
        print("上传进度: \(progress.fractionCompleted)")
    }
    .responseJSON { response in
        debugPrint(response)
    }

多部分表单上传

let imageData = UIImage(named: "cat")!.jpegData(compressionQuality: 0.8)!
AF.upload(multipartFormData: { multipartFormData in
    multipartFormData.append(imageData, withName: "file", fileName: "cat.jpg", mimeType: "image/jpeg")
    multipartFormData.append("field1_value".data(using: .utf8)!, withName: "field1")
}, to: "https://httpbin.org/post")
    .responseDecodable(of: UploadResponse.self) { response in
        print(response)
    }

下载文件

Alamofire 自动管理下载任务的临时文件和目标位置。

let destination: DownloadRequest.Destination = { _, _ in
    let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let fileURL = documentsURL.appendingPathComponent("video.mp4")
    return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}

AF.download("https://example.com/video.mp4", to: destination)
    .downloadProgress { progress in
        print("下载进度: \(progress.fractionCompleted)")
    }
    .response { response in
        if let error = response.error {
            print("下载失败: \(error)")
        } else {
            print("下载完成,文件位置: \(response.fileURL!)")
        }
    }

如需恢复中断的下载,可提前保存 resumeData

请求拦截与适配

RequestInterceptor 协议

自定义拦截器可以实现请求适配、重试逻辑。最常见的场景是在 Token 过期时自动刷新。

class AuthenticationInterceptor: RequestInterceptor {
    let tokenManager: TokenManager

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

    func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
        guard let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 else {
            return completion(.doNotRetry)
        }
        tokenManager.refreshToken { success in
            completion(success ? .retry : .doNotRetry)
        }
    }
}

将此拦截器注入到自定义 Session 实例中即可全局生效:

let session = Session(interceptor: AuthenticationInterceptor(tokenManager: tokenManager))
session.request("https://api.example.com/secure-data").responseJSON { ... }

网络可达性检测

let manager = NetworkReachabilityManager()
manager?.startListening { status in
    switch status {
    case .notReachable:
        print("网络不可用")
    case .reachable(.ethernetOrWiFi):
        print("通过 WiFi 连接")
    case .reachable(.cellular):
        print("通过蜂窝网络连接")
    case .unknown:
        print("未知状态")
    }
}

注意在不需要时调用 stopListening() 释放资源。

使用 async/await(iOS 13+, Swift 5.5+)

Alamofire 5.5 开始原生支持 Swift 并发,使异步代码更加简洁。

func fetchUsers() async throws -> [User] {
    let response = await AF.request("https://api.example.com/users")
                           .serializingDecodable([User].self)
                           .response
    switch response.result {
    case .success(let users):
        return users
    case .failure(let error):
        throw error
    }
}

或使用 responseDecodable 的便捷方法:

let users = try await AF.request("https://api.example.com/users")
                        .serializingDecodable([User].self)
                        .value

请求路由与 URLRequestConvertible

将 API 接口定义为枚举,并遵循 URLRequestConvertible 协议,可以使网络层组织更清晰。

enum UserRouter: URLRequestConvertible {
    case getUsers(page: Int)
    case createUser(parameters: Parameters)

    var baseURL: URL {
        URL(string: "https://api.example.com")!
    }

    var path: String {
        switch self {
        case .getUsers: return "/users"
        case .createUser: return "/users"
        }
    }

    var method: HTTPMethod {
        switch self {
        case .getUsers: return .get
        case .createUser: return .post
        }
    }

    func asURLRequest() throws -> URLRequest {
        let url = baseURL.appendingPathComponent(path)
        var request = URLRequest(url: url)
        request.method = method

        switch self {
        case .getUsers(let page):
            request = try URLEncoding.default.encode(request, with: ["page": page])
        case .createUser(let parameters):
            request = try JSONEncoding.default.encode(request, with: parameters)
        }
        return request
    }
}

// 使用
AF.request(UserRouter.getUsers(page: 2)).responseJSON { ... }

结构与错误处理

Alamofire 的所有错误均遵循 AFError 枚举,包含以下常见成员:

  • invalidURL:URL 无效
  • responseSerializationFailed:序列化失败
  • requestAdaptationFailed:适配失败
  • sessionTaskFailed:底层任务失败
  • serverTrustEvaluationFailed:SSL/TLS 评估失败

通过 validate() 可以自动将非期望的状态码和内容类型转换为错误。

性能优化与最佳实践

  • 重用 Session:不要为每次请求新建 Session,使用单例或基于作用域的管理器。
  • 并发请求:利用 withTaskGroupTaskGroup 与 async/await 配合请求。
  • 响应缓存:Alamofire 依赖底层的 URLCache,可通过配置 session.configuration.urlCache 实现缓存策略。
  • SSL Pinning:在安全要求极高的场景下,使用 ServerTrustManager 和证书绑定。
  • 日志与调试:开发阶段可以创建 EventMonitor 对象来记录请求/响应的详细信息。
let monitor = ClosureEventMonitor()
monitor.requestDidFinish = { request in
    print("请求完成: \(request)")
}

let session = Session(eventMonitors: [monitor])

总结

Alamofire 是 Swift 网络编程的不二之选。它平衡了高级抽象和底层控制,从简单的 JSON 获取到复杂的 Token 刷新、上传下载任务,都能以高度可读的链式代码实现。熟练掌握其核心模式,将显著提升你的开发效率和 App 的可靠性。

下一步,建议前往 Alamofire 官方文档 查阅更深入的高级特性,或动手编写一个涵盖拦截器、路由和并发请求的示例项目,巩固所学知识。