Swift-带委托的可重用URL请求 [英] Swift - Reusable URL Request with Delegates

查看:79
本文介绍了Swift-带委托的可重用URL请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我是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.

数据是安全的,因为如果错误 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆