Swift - 可重复使用 URL 请求委托
Swift - Reusable URL Request with Delegates
你好我是 Swift 的新手,我正在尝试为 URL 请求创建一个可重用的通用下载管理器,它可以在我的项目中的不同视图控制器中重用或在同一个视图控制器中重用VC 为不同的 URL 请求调用。我遇到的问题是如何将数据类型从请求传递到下载管理器,然后 return 将下载的数据返回到具有相应数据类型的 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,它应该 return 数据用于不同的模型类型(定义为结构)
downloadManager.downloadRequest(模式类型:Type2.self,参数:参数)
数据模型定义为结构:
struct DataModel2: Codable {
let EmployeeeID: String
}
在 Swift 次 Protocol/Delegate 闻起来有点 objective-c-ish.
我推荐一个具有通用 Result
类型的完成处理程序。
它 returns 泛型类型在成功时是非可选的,在失败时是任何错误。
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))
}
}
}
并使用它
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 请求创建一个可重用的通用下载管理器,它可以在我的项目中的不同视图控制器中重用或在同一个视图控制器中重用VC 为不同的 URL 请求调用。我遇到的问题是如何将数据类型从请求传递到下载管理器,然后 return 将下载的数据返回到具有相应数据类型的 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,它应该 return 数据用于不同的模型类型(定义为结构)
downloadManager.downloadRequest(模式类型:Type2.self,参数:参数)
数据模型定义为结构:
struct DataModel2: Codable {
let EmployeeeID: String
}
在 Swift 次 Protocol/Delegate 闻起来有点 objective-c-ish.
我推荐一个具有通用 Result
类型的完成处理程序。
它 returns 泛型类型在成功时是非可选的,在失败时是任何错误。
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))
}
}
}
并使用它
downloadManager.downloadrequest(modeType: Type1.self, parameters: parameters) { result in
switch result {
case .success(let data): print(data)
case .failure(let error): print(error)
}
}