[嗨,我是Swift的新手,我正在尝试为URL请求创建可重用的通用下载管理器,该管理器可以在我的整个项目中的不同View Controller中重用,也可以在同一VC中为不同的URL请求调用重用。我遇到的问题是如何将数据类型从请求传递到下载管理器,然后将具有相应数据类型的已下载数据返回给VC。我可以在对downloadRequest的调用中传递数据类型,但是我不知道如何通过委托DownloadManagerDelegate将数据类型传递回VC。任何帮助将不胜感激!
通用下载管理器:
protocol DownloadManagerDelegate {
func didUpdateData<T: Codable>(modelType: T.Type, downloadedData: T.Type)
}
struct DownloadManager {
var delegate: DownloadManagerDelegate?
func downloadRequest<T: Codable>(modelType: T.Type, parameters: [String: Any]) {
guard let url = URL(string: "https://www.someAPI...") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
guard let httpBodyWithParameters = try? JSONSerialization.data(withJSONObject: parameters, options: []) else
{
print("error")
return
}
request.httpBody = httpBodyWithParameters
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if error != nil {
print("error")
return
}
if let safeData = data {
if let downloadedData = parseDownloadedData(data: safeData) {
self.delegate?.didUpdateData(modelType: modelType, downloadedData: downloadedData)
}
}
}.resume()
func parseDownloadedData(data: Data) -> T?{
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(T.self, from: data)
return decodedData
} catch {
print(error)
return nil
}
}
}
在我的VC中委托:
override func viewDidLoad() {
super.viewDidLoad()
downloadManager.delegate = self
}
func didUpdateData(modelType: modelType,downloadedData:downloadedData){
DispatchQueue.main.async {
print(downloadedData)
}
}
致电下载downloadRequest:
downloadManager.downloadrequest(modeType: Type1.self, parameters: parameters)
[数据模型定义为结构:
struct DataModel1: Codable {
let ItemID: String
}
然后在同一VC中,我调用了相同的函数downloadManager,它将调用不同的API,该API应该返回不同模型类型(定义为Struct的数据)]
downloadManager.downloadRequest(modeType:Type2.self,参数:参数)
[数据模型定义为结构:
struct DataModel2: Codable {
let EmployeeeID: String
}
我建议使用通用的Result
类型的完成处理程序。
data
的力解开是安全的,因为如果error
为nil
,则data
具有值
struct DownloadManager {
func downloadRequest<T: Decodable>(modelType: T.Type, parameters: [String: Any], completion : @escaping (Result<T, Error>) -> Void) {
guard let url = URL(string: "https://www.someAPI...") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
do {
let httpBodyWithParameters = try JSONSerialization.data(withJSONObject: parameters)
request.httpBody = httpBodyWithParameters
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let error = error {
completion(.failure(error))
} else {
completion( Result { try JSONDecoder().decode(T.self, from: data!)})
}
}.resume()
} catch {
completion(.failure(error))
}
}
}