[英]How can i make my Networking class generic in Swift?
Here i am extracting data as DataModel .在这里,我将数据提取为DataModel 。 But i want to make this class generic and pass the model myself so that i can use it to parse data from multiple API's.
但我想让这个 class 通用并自己传递 model 以便我可以使用它来解析来自多个 API 的数据。 Can Anyone Help?
任何人都可以帮忙吗?
import Foundation
struct NetworkManager {
func fetchData(url : String, completion : @escaping (DataModel?) -> ()) {
print("Neeraj here")
let sessionURL = URL(string: url)
let session = URLSession(configuration: .default)
let dataTask = session.dataTask(with: sessionURL!) { (data, response, error) in
if error == nil {
if let safeData = data {
if let parsedData = self.parseData(data : safeData) {
print("got data")
completion(parsedData)
}
else {
debugPrint("failed to fetch data")
completion(nil)
}
}
}
else {
print("error in data task is \(String(describing: error))")
completion(nil)
}
}
dataTask.resume()
}
func parseData(data : Data) -> DataModel? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(DataModel.self, from: data)
return decodedData
} catch {
print("error while parsing data \(error)")
return nil
}
}
}
With the convenient Result
type you can write a quite tiny generic method, it returns the decoded type on success and any error on failure使用方便的
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()
}
Note: Force unwrapping data!
注意:强制解包
data!
is 100% safe if no error occurs如果没有发生错误,是 100% 安全的
Be aware that you have to specify the concrete type when you are going to call the method请注意,当您要调用该方法时,您必须指定具体类型
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)
}
}
You can add a generic type constraint (called Model
) which conforms Decodable
like below:您可以添加符合
Decodable
的通用类型约束(称为Model
),如下所示:
struct NetworkManager {
func fetchData<Model: Decodable>(url : String, completion : @escaping (Model?) -> ()) {
let sessionURL = URL(string: url)
let session = URLSession(configuration: .default)
let dataTask = session.dataTask(with: sessionURL!) { (data, response, error) in
if error == nil {
if let safeData = data {
do {
let decodedData = try JSONDecoder().decode(Model.self, from: safeData)
completion(decodedData)
} catch {
print("error while parsing data \(error)")
}
} else {
debugPrint("failed to fetch data")
completion(nil)
}
}
else {
print("error in data task is \(String(describing: error))")
completion(nil)
}
}
dataTask.resume()
}
}
struct SampleModel: Decodable {
let name: String
}
NetworkManager().fetchData(url: "") { (data: SampleModel?) in
print(data)
}
You can write a generic function to fetch data like this one:您可以编写一个通用的 function 来获取这样的数据:
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()
}
}
I suppose that you have a data model, if you have not, you should create for your every object.我想你有一个数据 model,如果你没有,你应该为你的每个 object 创建。 Also by using a dummy URL i will make a request and fetch the JSON includes some users name and ids with JSON format.
此外,通过使用虚拟 URL 我将发出请求并获取 JSON 包括一些用户名和 id 格式为 JSON。 Let`s define a data model for this:
让我们为此定义一个数据 model:
struct StackUser: Decodable {
let id: Int
let name: String
}
fetchGenericData(urlString: "https://api.stackoverexample.com/stackusers") { (stackUsers: [StackUser]) in
stackUsers.forEach({print($0.name)})
}
Finally you will be parse the data and prints like this:最后,您将解析数据并打印如下:
Rob
Matt
Vadian
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.