【问题标题】:Swift - Reusable URL Request with DelegatesSwift - 可重用的带有委托的 URL 请求
【发布时间】:2020-03-07 16:25:55
【问题描述】:

您好,我是 Swift 新手,我正在尝试为 URL 请求创建一个可重用的通用下载管理器,它可以在我的整个项目中的不同视图控制器中重用,或者在同一个 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, parameters: 参数)

数据模型被定义为一个结构:

  struct DataModel2: Codable {
       let EmployeeeID: String
    }

【问题讨论】:

    标签: swift delegates nsurlrequest


    【解决方案1】:

    在 Swift 时代,Protocol/Delegate 有点objective-c-ish

    我推荐使用多功能Result 类型的完成处理程序。

    成功时返回非可选的泛型类型,失败时返回任何错误。

    data 的强制展开是安全的,因为如果 errornildata 有一个值

    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)
        }
    }
    

    【讨论】:

    • 谢谢!我如何将结果传递回原始 VC?假设我想在原始 VC 上更新 label.text
    猜你喜欢
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    • 2012-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多