【问题标题】:In SwiftUI, how can return a function only when an API request is finished? [duplicate]在 SwiftUI 中,如何仅在 API 请求完成时才返回函数? [复制]
【发布时间】:2021-12-25 01:10:13
【问题描述】:

我正在尝试学习一些关于在 SwiftUI 中进行 API 调用的知识。 我有一个名为 loadData 的函数,它通过 onAppear 修饰符运行。

该函数的目标是查看我当前在 CoreData 中是否有数据。
如果 CoreData 中没有数据,那么我想调用另一个函数来调用 API 来获取数据,但只返回获取的数据。

在下面的示例中,getCurrentSol 函数在异步部分完成之前返回。导致没有数据被返回。我返回数据的合适方式是什么?

如您所见,我确实尝试了一段时间(真实)“技巧”。但无论出于何种原因,我的 results 变量甚至都不会使用获取的数据进行更新,即使 decodedData 变量确实包含正确的结果。

}.onAppear(perform: loadData)
}

func loadData() {
    print("data: \(storedData) ")
    print("data.count: \(storedData.count)")
    
    if(storedData.count == 0){
        let fetchedData = getCurrentSol()
        let currentSol = fetchedData.sol
        print("fetchedData: \(fetchedData)")
        print("currentSol: \(currentSol)")

    }
    
}

func getCurrentSol() -> CuriosityRoverModel {
    var results =  CuriosityRoverModel(sol: 0, low: 0, high: 0, opacity: "Sunny", sunrise: "00:00", sunset: "00:00", month: "Month 0")
    let urlString = "https://api.maas2.apollorion.com"
    let url = URL(string: urlString)
    URLSession.shared.dataTask(with: url!) {data, response, error in
        DispatchQueue.main.async {
            if let data = data {
                do {
                    let decoder = JSONDecoder()
                    let decodedData = try decoder.decode(CuriosityRoverModel.self, from: data)
                    //This recieves the proper data, but it doesn't get written to the results var
                    print("decodedData: \(decodedData)")
                    results = decodedData
                } catch {
                    print("Error: ", error)
                }
            }
        }
    }.resume()
    // I thought this would be a way to wait for the data
    // but results never gets updated so it ends up running endlessly
    while(true){
        if(results.sol > 0){
            return results
        }
    }
    //return results // This would just return the "empty" results var from above before the data is actually retrieved
}

}

【问题讨论】:

标签: swift swiftui


【解决方案1】:

有很多方法可以实现您想要的。这是一种方法,使用闭包:

    ....
       .onAppear(perform: loadData)
}

func loadData() {
    print("data: \(storedData) ")
    print("data.count: \(storedData.count)")
    
    if (storedData.count == 0) {
        getCurrentSol() { results in    // <--- here
            if let fetchedData = results {
                let currentSol = fetchedData.sol
                print("fetchedData: \(fetchedData)")
                print("currentSol: \(currentSol)")
            }
        }
    }
}

// use a completion closure to "return" your results when done, not before
func getCurrentSol(completion: @escaping (CuriosityRoverModel?) -> Void) {
    let urlString = "https://api.maas2.apollorion.com"
    let url = URL(string: urlString)
    URLSession.shared.dataTask(with: url!) {data, response, error in
        DispatchQueue.main.async {
            if let data = data {
                do {
                    let decoder = JSONDecoder()
                    let decodedData = try decoder.decode(CuriosityRoverModel.self, from: data)
                    print("decodedData: \(decodedData)")
                    completion(decodedData)  // <--- here, return the results
                } catch {
                    print("Error: ", error) // need to deal with errors
                    completion(nil)   // <--- here, should return the error
                }
            }
        }
    }.resume()
}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-23
    • 1970-01-01
    • 2019-05-25
    • 1970-01-01
    • 2021-09-30
    • 2020-03-14
    • 2020-04-12
    相关资源
    最近更新 更多