Return HTTP 请求数据

Return HTTP request data

我想 return 来自我的方法 getAllPoints()

的变量点
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}
]

我想知道这是否有可能 return 在我的方法的最后。 我将在 pickerView 中使用它并进行 CRUD,这就是我想要存储它们的原因。

谢谢

使用完成闭包来“return”你的分数。 尝试这样的事情:

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

我的理解是,您希望在调用函数的位置得到 api 响应。您可以 return 使用闭包来回复。

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

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

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

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

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

首先请以大写字母(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)
    }
}