【问题标题】:Return HTTP request data返回 HTTP 请求数据
【发布时间】:2021-12-31 04:23:31
【问题描述】:

我想从我的方法 getAllPoints() 中返回 var 点

struct tempPoint: Decodable {
    let idPoint:Int
    let ptName:String
    let ptLat:Double
    let ptLong:Double
}

func getAllPoints(){

if let url = URL(string: "[MyWebService.com]") {
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let data = data {
                if let jsonString = String(data: data, encoding: .utf8) {
                    let jsonData = Data(jsonString.utf8)
                    do {
                        let points = try JSONDecoder().decode([tempPoint].self, from: jsonData)
                    } catch let error {
                        print(error)
                    }
                    print(jsonString)
                }
            }
        }.resume()
    }
}

打印时得到的结果(点数)

[
{"idPoint":6,"ptName":"Maison","ptLat":43.72623997050257,"ptLong":2.202591651830584},
{"idPoint":7,"ptName":"Wheelin","ptLat":42.75754326128173,"ptLong":8.137330631668685},
{"idPoint":8,"ptName":"Animoz","ptLat":45.76321863196126,"ptLong":7.137186047202841},
{"idPoint":9,"ptName":"Hesias","ptLat":45.767222865412144,"ptLong":6.132352002277385},
{"idPoint":10,"ptName":"Marcombes","ptLat":45.76018235160473,"ptLong":4.085466264251463},
{"idPoint":11,"ptName":"Leclan","ptLat":48.80950120948317,"ptLong":2.110623123039061},
{"idPoint":12,"ptName":"Cournon Skatepark","ptLat":39.74138613175866,"ptLong":4.2154977334348906}
]

我想知道这是否可以在我的方法结束时返回这些。 我将在 pickerView 中使用它并执行 CRUD,这就是我想存储它们的原因。

谢谢

【问题讨论】:

  • 你能分享一下你想以哪种格式返回,比如只返回点还是数组?

标签: arrays swift http


【解决方案1】:

使用完成闭包“返还”您的积分。 试试这样的:

func getAllPoints(completion: @escaping([tempPoint]) -> ()) {  // <-- here
    if let url = URL(string: "[MyWebService.com]") {
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let data = data {
                do {
                    let points = try JSONDecoder().decode([tempPoint].self, from: data)
                    completion(points)  // <-- here return the results when done
                    return
                } catch let error {
                    print(error) // <-- here todo deal with errors
                }
            }
            completion([]) // <-- here todo deal with errors
        }.resume()
    } else {
        completion([]) // <-- here todo deal with errors
    }
}

然后像这样调用函数:

getAllPoints() { results in
      print("array of points: \(results)")
}

【讨论】:

    【解决方案2】:

    我的理解是,您希望 api 响应位于调用函数的位置。您可以使用闭包返回您的响应。

    您在以下代码中看到的 typealias 是自定义数据类型。您可以直接在函数中添加闭包,但为了让您更简单,我将这些闭包声明为 typealias 作为数据类型。您可以在此处阅读有关typealiasclosures 的更多信息。

    在声明了我们自己的闭包类型之后。我们需要在函数中使用它们作为参数。

    struct TempPoint: Decodable {
            let idPoint:Int
            let ptName:String
            let ptLat:Double
            let ptLong:Double
        }
        
        typealias ApiResponse = ([TempPoint]) -> Void
        typealias ApiError = (Error) -> Void
        
        func getAllPoints(_ completion: @escaping ApiResponse, apiError: @escaping ApiError){
            
            if let url = URL(string: "[MyWebService.com]") {
                URLSession.shared.dataTask(with: url) { data, response, error in
                    if let data = data {
                        if let jsonString = String(data: data, encoding: .utf8) {
                            let jsonData = Data(jsonString.utf8)
                            do {
                                let points = try JSONDecoder().decode([TempPoint].self, from: jsonData)
                                completion(points)
                            } catch let error {
                                print(error)
                                apiError(error)
                            }
                            print(jsonString)
                        }
                    }
                }.resume()
            }
        }
    

    修改后的函数如上所示。

    下面是我们如何使用这个函数。

    override func viewDidLoad() {
        super.viewDidLoad()
        
        getAllPoints { [weak self] (points) in
            // you update you UI here, be sure to call in main thread when you are doing UI updates in closures.
            print(points)
        } apiError: { (error) in
            print(error)
        }
        
    }
    

    【讨论】:

      【解决方案3】:

      如果事情是松散耦合的,这将是有效的,这可以通过委托模式来完成。

         protocol TempPointDelegate {
          func didUpdatePoints(_ tempPoints: [tempPoint])
          func didFailWithError(error: Error)
      }
      

      在 tempPoint 结构中

          struct tempPoint: Decodable {
              let idPoint:Int
              let ptName:String
              let ptLat:Double
              let ptLong:Double
          }
          
          var delegate: TempPointDelegate?
          
          func getAllPoints(){
          
          if let url = URL(string: "[MyWebService.com]") {
                  URLSession.shared.dataTask(with: url) { data, response, error in
                      if let data = data {
                          if let jsonString = String(data: data, encoding: .utf8) {
                              let jsonData = Data(jsonString.utf8)
                              do {
                                  let points = try JSONDecoder().decode([tempPoint].self, from: jsonData)
                                  self.delegate?.didUpdatePoints(points)
                                  return
                              } catch let error {
                                  self.delegate?.didFailWithError(error)
                                  return
                              }
                          }
                      }
                  }.resume()
              }
          }
          
      

      最后在你的 ViewController 中实现 tempPointDelegate 委托

       class MainViewController: tempPointDelegate{
            override func viewDidLoad() {
                   super.viewDidLoad()
                   tempPoint.getAllPoints()
            }
           func didUpdatePoints(_ tempPoints: [tempPoint]) {
                  DispatchQueue.main.async {
                  //process the tempPoints here / call the func to handle tempPoints
                  }
          }
          
          func didFailWithError(error: Error) {
              //process the error returned here.
          }
      }
      

      【讨论】:

        【解决方案4】:

        首先请以大写字母 (TempPoint) 命名结构体。

        第二次转换为String 并返回Data 毫无意义

        在 Swift 5.5 中,您可以使用 async/await

        func getAllPoints() async throws -> [TempPoint] {
        
            guard let url = URL(string: "[MyWebService.com]") else { throw URLError(.badURL) }
            let (data, _) = try await URLSession.shared.data(from : url)
            return try JSONDecoder().decode([TempPoint].self, from: data)
        }
        

        然后叫它

        Task {
            do {
               let points = try await getAllPoints()
            } catch {
                print(error)
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-10-16
          • 2021-06-28
          • 2014-03-27
          • 1970-01-01
          • 2011-12-10
          • 2020-12-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多