Ios 如何使我的网络课程在Swift中通用?
在这里,我将数据提取为DataModel。但是我想让这个类成为泛型类,并自己传递模型,这样我就可以使用它来解析来自多个API的数据。有人能帮忙吗 <代码>导入基础 结构网络管理器{ func fetchData(url:String,completion:@escaping(DataModel?)->()){ 打印(“此处为Neeraj”) 让sessionURL=URL(字符串:URL) let session=URLSession(配置:。默认值) 让dataTask=session.dataTask(带:sessionURL!){(数据、响应、错误)在 如果错误==nil{ 如果让safeData=data{ 如果让parsedData=self.parseData(数据:safeData){ 打印(“获取数据”) 完成(解析数据) } 否则{ debugPrint(“无法获取数据”) 完成(无) } } } 否则{ 打印(“数据任务中的错误为\(字符串(描述:错误))”) 完成(无) } } dataTask.resume() } func parseData(数据:数据)->数据模型{ let decoder=JSONDecoder() 做{ 让decodedData=try decoder.decode(DataModel.self,from:data) 返回解码数据 }抓住{ 打印(“分析数据时出错\(错误)”) 归零 } } }Ios 如何使我的网络课程在Swift中通用?,ios,swift,Ios,Swift,在这里,我将数据提取为DataModel。但是我想让这个类成为泛型类,并自己传递模型,这样我就可以使用它来解析来自多个API的数据。有人能帮忙吗 导入基础 结构网络管理器{ func fetchData(url:String,completion:@escaping(DataModel?)->()){ 打印(“此处为Neeraj”) 让sessionURL=URL(字符串:URL) let session=URLSession(配置:。默认值) 让dataTask=session.dataTas
您可以添加一个通用类型约束(称为
模型
),该约束符合可解码
,如下所示:
struct NetworkManager{
func fetchData(url:String,completion:@escaping(Model?)->()){
让sessionURL=URL(字符串:URL)
let session=URLSession(配置:。默认值)
让dataTask=session.dataTask(带:sessionURL!){(数据、响应、错误)在
如果错误==nil{
如果让safeData=data{
做{
让decodedData=try JSONDecoder().decode(Model.self,from:safeData)
完成(解码数据)
}抓住{
打印(“分析数据时出错\(错误)”)
}
}否则{
debugPrint(“无法获取数据”)
完成(无)
}
}
否则{
打印(“数据任务中的错误为\(字符串(描述:错误))”)
完成(无)
}
}
dataTask.resume()
}
}
用法
struct SampleModel:可解码{
let name:String
}
NetworkManager().fetchData(url:){(数据:SampleModel?)位于
打印(数据)
}
您可以编写一个通用函数来获取如下数据:
func fetchGenericData<T: Decodable>(urlString: String, completion: @escaping (T) -> ()) {
let url = URL(string: urlString)
URLSession.shared.dataTask(with: url!) { (data, resp, err) in
if let err = err {
print("Failed to fetch data:", err)
return
}
guard let data = data else { return }
do {
let obj = try JSONDecoder().decode(T.self, from: data)
completion(obj)
} catch let jsonErr {
print("Failed to decode json:", jsonErr)
}
}.resume()
}
}
最后,您将解析数据并按如下方式打印:
Rob
Matt
Vadian
使用方便的
Result
类型,您可以编写一个非常小的泛型方法,成功时返回解码类型,失败时返回任何错误
func fetchData<T: Decodable>(urlString: String, completion: @escaping (Result<T,Error>) -> Void) {
guard let url = URL(string: urlString) else { return } // or throw an error
URLSession.shared.dataTask(with: url) { (data, _, error) in
if let error = error { completion(.failure(error)); return }
completion( Result{ try JSONDecoder().decode(T.self, from: data!) })
}.resume()
}
DataModel
是Codable
,因此您可能需要将其用于通用部件。但是你试过什么吗?您有一个非常简单的通用代码。如果需要,可以先将parseData
代码放在fetch代码中,然后理解泛型,我不是在问使用泛型,而是在问如何自己传递数据模型,以便处理来自这个单一类的多个API。我应该如何调用它?我之前调用它就像self.networkManager.fetchData(url:url){(data)init给出的“无法推断泛型参数‘T’”错误我已经更新了我的答案,请检查@neerajgupta谢谢你的帮助@sonie。我知道了,我可以使用泛型来完成任务。也谢谢你的帮助@zeytin。我看到你在使用警卫,我喜欢你的方法。你写的代码如此干净。我认为这是一种更优雅的方法,因为它允许你访问错误这可能来自网络、操作系统或解码过程。此外,我不知道init(catching:)
Result的初始值设定项存在:),尽管我倾向于将所有错误映射到自定义错误类型。
func fetchData<T: Decodable>(urlString: String, completion: @escaping (Result<T,Error>) -> Void) {
guard let url = URL(string: urlString) else { return } // or throw an error
URLSession.shared.dataTask(with: url) { (data, _, error) in
if let error = error { completion(.failure(error)); return }
completion( Result{ try JSONDecoder().decode(T.self, from: data!) })
}.resume()
}
fetchData(urlString: "https://example.com/api") { (result : Result<MyModel,Error>) in
switch result {
case .success(let model): print(model)
case .failure(let error): print(error)
}
}