Swift-带委托的可重用URL请求 [英] Swift - Reusable URL Request with Delegates
问题描述
您好,我是Swift的新手,我正在尝试为URL请求创建可重用的通用下载管理器,该管理器可在我的整个项目中的不同View Controller中重用,或在同一VC中为不同的URL Request调用重用。我遇到的问题是如何将数据类型从请求传递到下载管理器,然后将具有相应数据类型的已下载数据返回给VC。我可以在对downloadRequest的调用中传递数据类型,但是我不知道如何通过委托DownloadManagerDelegate将数据类型传递回VC。任何帮助将不胜感激!
Hi I'm new to Swift and I am trying to create a reusable generic Download Manager for URL Request that can be reused throughout my project in different View Controllers or reused within the same VC for a different URL Request calls. The problem that I have is how do I pass the Data Type from the Request into the Download Manager and then return the Downloaded Data back to the VC with the corresponding Data Type. I am able to pass the Data Type in a call to downloadRequest but I can't figure out how to pass the Data Type back to the VC via a delegate DownloadManagerDelegate. Any help would be greatly appreciate it!
通用下载管理器:
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)
}
}
呼叫下载下载请求:
downloadManager.downloadrequest(modeType: Type1.self, parameters: parameters)
数据模型定义为结构:
struct DataModel1: Codable {
let ItemID: String
}
然后在同一VC中,我调用同一函数downloadManager,该函数将调用不同的API,该API应返回不同模型类型(定义为Struct)的数据
Then in the same VC I call the same function downloadManager that will call a different API which should return data for a different Model Type (defined as Struct)
downloadManager.downloadRequest(modeType:Type2.self,参数:参数)
downloadManager.downloadRequest(modeType: Type2.self, parameters: parameters)
数据模型定义为结构:
struct DataModel2: Codable {
let EmployeeeID: String
}
推荐答案
在迅速时期,Protocol / Delegate闻起来有点 objective-c-ish 。
In the Swift times Protocol/Delegate smells a bit objective-c-ish.
我建议使用通用的 Result
类型的完成处理程序。
I recommend a completion handler with the versatile Result
type.
成功时返回通用类型,失败则返回错误。
It returns the generic type non-optional on success and any error on failure.
数据$ c $的强制展开c>是安全的,因为如果
错误
为 nil
,则 data
具有值
The force unwrapping of data
is safe because if error
is nil
then data
has a value
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))
}
}
}
并使用它
downloadManager.downloadrequest(modeType: Type1.self, parameters: parameters) { result in
switch result {
case .success(let data): print(data)
case .failure(let error): print(error)
}
}
这篇关于Swift-带委托的可重用URL请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!