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

Swift4/iOS开发:如何将协议传入Completion Handler实现泛型JSON解析

通用Swift网络请求+泛型JSON解析方案

早上好呀Stack Overflow社区的小伙伴!很高兴能帮你解决这个Swift网络编程里的泛型解析问题~你想要实现的通用网络请求逻辑完全可行,核心就是利用泛型约束和Result类型来完美适配任意Decodable对象,同时避开协议传参带来的坑。

核心思路

你之前遇到的问题,大概率是直接把Decodable协议类型传给了Completion Handler——这会因为Swift的协议类型擦除,导致JSONDecoder无法确定具体要解析的对象类型。而用泛型的话,编译器会在调用时锁定具体的模型类型,就能让解析正常工作了。

完整实现代码

先写一个通用的网络请求函数,它接受任意遵循Decodable的泛型类型,并用Result类型统一处理成功/失败的回调:

import Foundation

func fetchDecodableData<T: Decodable>(from url: URL, completion: @escaping (Result<T, Error>) -> Void) {
    // 发起URLSession请求
    URLSession.shared.dataTask(with: url) { data, response, error in
        // 优先处理请求错误
        if let requestError = error {
            completion(.failure(requestError))
            return
        }
        
        // 校验是否获取到有效数据
        guard let responseData = data else {
            let noDataError = NSError(domain: "NetworkError", code: 1001, userInfo: [
                NSLocalizedDescriptionKey: "未获取到响应数据"
            ])
            completion(.failure(noDataError))
            return
        }
        
        // 尝试解析JSON
        do {
            let decodedObject = try JSONDecoder().decode(T.self, from: responseData)
            completion(.success(decodedObject))
        } catch let decodingError {
            completion(.failure(decodingError))
        }
    }.resume() // 别忘了启动任务!
}

如何复用这个通用函数

假设你有一个自定义的User模型,遵循Decodable:

struct User: Decodable {
    let id: Int
    let username: String
    let email: String
}

调用通用请求函数时,Swift会自动推断泛型类型,你也可以显式指定:

// 替换成你的实际接口地址
guard let userUrl = URL(string: "https://api.example.com/users/1") else {
    print("无效的URL")
    return
}

// 发起请求,Swift会自动推断T是User类型
fetchDecodableData(from: userUrl) { result in
    switch result {
    case .success(let user):
        print("成功获取用户:\(user.username),邮箱:\(user.email)")
    case .failure(let error):
        print("请求失败:\(error.localizedDescription)")
    }
}

如果要解析其他模型(比如Post),只需要定义好遵循Decodable的Post结构体,直接复用这个函数就行,完全不需要修改请求逻辑。

关键点说明

  • 泛型约束<T: Decodable>:确保传入的类型必须符合Decodable协议,让JSONDecoder能正确匹配模型结构。
  • Result<T, Error>类型:统一处理成功和失败的回调,比传统的(T?, Error?)更清晰,避免出现两者都为nil或都有值的混乱情况。
  • 避开协议类型直接传参:泛型在编译时会确定具体的类型,解决了直接用Decodable作为参数时的类型擦除问题,让解析器能准确完成工作。

这样你就拥有了一个可以无限复用的通用网络请求工具,不管是解析用户、文章还是其他任何自定义模型,都能直接套用啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:07:21