【问题标题】:Swift - Multiple URL Request - Code To Refactor and To ReuseSwift - 多个 URL 请求 - 重构和重用的代码
【发布时间】:2020-02-28 20:23:11
【问题描述】:

我是 Swift 新手,我正在尝试重构我的 URL Post 请求。我在同一个视图控制器中有多个 URL POST 请求,就像这样。一切正常,但在我看来,有很多可以重用的重复代码。特别是,我不知道如何传递/处理应该在 parseRequest1 和 parseRequest2 中使用的不同数据模型。我还读到在同一个项目中应该只有一个会话用于 URL 请求。任何帮助将不胜感激!

func request1() {        
    let parameters = [...//some parameters to send]
    guard let url = URL(string: "https//www.....") else {return}
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    guard let parametersToSend = try? JSONSerialization.data(withJSONObject: parameters, options: []) 
       else {
         print("Error")
         return
       }
    request.httpBody = parametersToSend
    let session = URLSession.shared
    session.dataTask(with: request) { (data, response, error) in
       if let safeData = data {
          self.parseRequest1(data: safeData)
        }
   }.resume()
}

func parseRequest1(data: Data){
    let decoder = JSONDecoder()
    do{
      let decodedData = try decoder.decode(DataModelForRequest1.self, from: data)
        DispatchQueue.main.async {
           self.performAction1(request1Result)
        }
    } catch {
       print(error)
    }
} 

然后我有另一个 URL 请求 request2,除了参数和用于在 parseRequest2 中进行解码和操作的模型之外几乎相同。

func request2() {        
        let parameters = [...//some parameters to send]
        guard let url = URL(string: "https//www.....") else {return}
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        guard let parametersToSend = try? JSONSerialization.data(withJSONObject: parameters, options: []) 
           else {
             print("Error")
             return
           }
        request.httpBody = parametersToSend
        let session = URLSession.shared
        session.dataTask(with: request) { (data, response, error) in
           if let safeData = data {
              self.parseRequest2(data: safeData)
            }
       }.resume()
    }

    func parseRequest2(data: Data){
        let decoder = JSONDecoder()
        do{
          let decodedData = try decoder.decode(DataModelForRequest2.self, from: data)
            DispatchQueue.main.async {
               self.performAction2(request2Result)
            }
        } catch {
           print(error)
        }
    } 

【问题讨论】:

    标签: swift nsurlrequest urlsession


    【解决方案1】:

    唯一的区别似乎是:

    • 请求参数
    • 返回的模型类型
    • 收到响应后您执行的操作

    这意味着我们可以将上述三个值作为参数写成一个单一的方法:

    func request<T: Codable>(modelType: T.Type, parameters: [String: Any], completion: (T) -> Void) {
    
        func parseResponse(data: Data){
            let decoder = JSONDecoder()
            do{
              let decodedData = try decoder.decode(T.self, from: data)
                DispatchQueue.main.async {
                  completion(decodedData)
                }
            } catch {
               print(error)
            }
        } 
    
        guard let url = URL(string: "https//www.....") else {return}
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        guard let parametersToSend = try? JSONSerialization.data(withJSONObject: parameters, options: []) 
           else {
             print("Error")
             return
           }
        request.httpBody = parametersToSend
        let session = URLSession.shared
        session.dataTask(with: request) { (data, response, error) in
           if let safeData = data {
              parseResponse(data: safeData)
            }
       }.resume()
    }
    

    然后您可以根据需要使用适当的参数调用此方法。

    【讨论】:

    • 谢谢!我将如何为 parseResponse 方法实现委托? protocol DownloadManagerDelegate { func didUpdateData&lt;T: Codable&gt;(modelType: T.Type, downloadedData: T.Type) }
    • @Luke 我不明白。委托与问题中的代码有何关系?请注意,我的答案中的 parseResponse 对应于您的 parseRequest 方法。我重命名它是因为我认为parseRequest 不是一个好名字。您是否将其与代码中的其他 parseResponse 混淆了?
    • 请看我正在尝试将 parseResponse 返回给调用 func Request 的 VC。我虽然我应该通过委托(而不是 parseResponse)self.delegate?.didUpdateData(modelType: modelType, downloadedData: downloadedData) 返回它。抱歉,我对 Swift 有点陌生,所以我希望它有意义。
    • 我发布了这个新问题,其中包含我现在所拥有的更多详细信息:stackoverflow.com/questions/60579710/…
    • @Luke 我猜你决定在问这个问题和现在之间的某个时刻做其他事情?当我有时间时,我会尝试回答另一个问题。同时,我的回答是否回答了this问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-03
    • 2021-10-30
    • 1970-01-01
    相关资源
    最近更新 更多