You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift通用网络层改造:支持GET/POST请求及授权实现指导

改造Swift网络层支持GET/POST及授权密钥处理

以下是针对你的需求的完整改造方案,核心是扩展网络层的通用性,同时解决GET/POST请求切换和授权密钥的问题:

1. 新增HTTP方法枚举

先定义支持的HTTP方法,方便后续扩展和统一管理:

enum HTTPMethod: String {
    case get = "GET"
    case post = "POST"
}

2. 重构网络层协议

修改HTTPDataDownloader协议,新增HTTP方法、请求头、请求体参数,让接口适配更多请求场景:

protocol HTTPDataDownloader {
    func fetchData<T: Decodable>(
        as type: T.Type,
        endpoint: String,
        method: HTTPMethod,
        headers: [String: String]?,
        body: Encodable?
    ) async throws -> T
}

3. 实现通用网络请求逻辑

更新协议扩展,根据不同HTTP方法构建请求,处理授权头和请求体编码:

extension HTTPDataDownloader {
    func fetchData<T: Decodable>(
        as type: T.Type,
        endpoint: String,
        method: HTTPMethod = .get,
        headers: [String: String]? = nil,
        body: Encodable? = nil
    ) async throws -> T {
        guard let url = URL(string: endpoint) else {
            throw APIError.requestFailed(description: "无效URL")
        }
        
        var request = URLRequest(url: url)
        request.httpMethod = method.rawValue
        
        // 注入自定义请求头(包括授权密钥)
        headers?.forEach { key, value in
            request.setValue(value, forHTTPHeaderField: key)
        }
        
        // 处理POST请求的JSON请求体
        if let body = body, method == .post {
            do {
                request.httpBody = try JSONEncoder().encode(body)
                request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            } catch {
                throw APIError.requestFailed(description: "请求体编码失败: \(error.localizedDescription)")
            }
        }
        
        let (data, response) = try await URLSession.shared.data(for: request)
        
        guard let httpResponse = response as? HTTPURLResponse else {
            throw APIError.requestFailed(description: "请求无响应")
        }
        
        // 放宽成功状态码范围,覆盖200-299的标准成功码
        guard (200...299).contains(httpResponse.statusCode) else {
            throw APIError.invalidStatusCode(statuscode: httpResponse.statusCode)
        }
        
        do {
            return try JSONDecoder().decode(type, from: data)
        } catch {
            throw error as? APIError ?? .unknownError(error: error)
        }
    }
}

4. 改造数据服务类,支持GET/POST请求

以CommentsDataService为例,添加POST请求方法,并演示授权密钥的使用方式:

// 定义POST请求需要的参数结构体(遵循Encodable)
struct CreateCommentRequest: Encodable {
    let postId: Int
    let name: String
    let email: String
    let body: String
}

class CommentsDataService: HTTPDataDownloader {
    private let baseUrl = "https://jsonplaceholder.typicode.com"
    // 示例授权密钥,实际项目中请用Keychain存储,不要硬编码
    private let authToken = "Bearer your_actual_auth_token"
    
    // 原有GET请求逻辑,可选择性添加授权头
    func fetchComments() async throws -> [Comments] {
        let endpoint = "\(baseUrl)/posts/1/comments"
        return try await fetchData(
            as: [Comments].self,
            endpoint: endpoint,
            method: .get,
            headers: ["Authorization": authToken]
        )
    }
    
    // 新增POST请求创建评论
    func createComment(request: CreateCommentRequest) async throws -> Comments {
        let endpoint = "\(baseUrl)/comments"
        return try await fetchData(
            as: Comments.self,
            endpoint: endpoint,
            method: .post,
            headers: ["Authorization": authToken],
            body: request
        )
    }
}

5. 更新ViewModel调用POST方法

在CommentsViewModel中添加创建评论的业务逻辑:

@Observable
class CommentsViewModel {
    var comments = [Comments]()
    var errorMessage: String?
    
    private let service: CommentsDataService
    
    init(service: CommentsDataService) {
        self.service = service
        Task { await fetchComments() }
    }
    
    @MainActor
    func fetchComments() async {
        do {
            self.comments = try await service.fetchComments()
        } catch {
            guard let error = error as? APIError else { return }
            self.errorMessage = error.customDescription
        }
    }
    
    // 添加创建评论的方法
    @MainActor
    func createNewComment(postId: Int, name: String, email: String, body: String) async {
        let request = CreateCommentRequest(postId: postId, name: name, email: email, body: body)
        do {
            let newComment = try await service.createComment(request: request)
            self.comments.append(newComment)
        } catch {
            guard let error = error as? APIError else { return }
            self.errorMessage = error.customDescription
        }
    }
}

核心要点说明

  • 授权密钥处理:通过headers参数传入Authorization字段,常见格式为Bearer token或Basic base64编码字符串,实际项目中务必用Keychain存储密钥,不要硬编码在代码里。
  • POST请求体:请求参数需遵循Encodable协议,通过JSONEncoder转为JSON数据,同时设置Content-Type为application/json适配接口要求。
  • 状态码判断:将原有的仅判断200改为判断200-299区间,符合HTTP标准的成功状态码范围。

内容的提问来源于stack exchange,提问作者NodlesView

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:07:02