【发布时间】:2021-05-25 00:22:41
【问题描述】:
目前我正在解码来自 API 的 JSON 响应并将其存储到结构“IPGeolocation”中。我希望能够将此数据存储在变量中或返回此结构的实例,以便我可以访问视图中的值。
结构:
struct IPGeolocation: Decodable {
var location: Coordinates
var date: String
var sunrise: String
var sunset: String
var moonrise: String
var moonset: String
}
struct Coordinates: Decodable{
var latitude: Double
var longitude: Double
}
带有函数 getResult 的 URL 扩展:
extension URL {
func getResult<T: Decodable>(completion: @escaping (Result<T, Error>) -> Void) {
URLSession.shared.dataTask(with: self) { data, response, error in
guard let data = data, error == nil else {
completion(.failure(error!))
return
}
do {
completion(.success(try data.decodedObject()))
} catch {
completion(.failure(error))
}
}.resume()
}
}
检索和解码数据的函数:
func getMoonTimes(lat: Double, long: Double) -> Void{
urlComponents.queryItems = queryItems
let url = urlComponents.url!
url.getResult { (result: Result<IPGeolocation, Error>) in
switch result {
case let .success(result):
print("Printing returned results")
print(result)
case let .failure(error):
print(error)
}
}
}
我的目标是获取解码后的信息并将其分配给我的结构,以便之后在视图中使用。一旦函数运行,结果变量已经是一个 IPGeolocation 结构。我的问题在于存储它的最佳方式,甚至在必要时将其退回。
让 getResult 返回 IPGeolocation 有意义吗?有更好/不同的方法吗?
谢谢!
编辑:感谢 Leo Dabus 以下 cmets 的帮助,我做出了更改。
func getMoonTimes(completion: @escaping (IPGeolocation?,Error?) -> Void) {
print("STARTING FUNC")
let locationViewModel = LocationViewModel()
let apiKey = "AKEY"
let latitudeString:String = String(locationViewModel.userLatitude)
let longitudeString:String = String(locationViewModel.userLongitude)
var urlComponents = URLComponents(string: "https://api.ipgeolocation.io/astronomy?")!
let queryItems = [URLQueryItem(name: "apiKey", value: apiKey),
URLQueryItem(name: "lat", value: latitudeString),
URLQueryItem(name: "long", value: longitudeString)]
urlComponents.queryItems = queryItems
urlComponents.url?.getResult { (result: Result<IPGeolocation, Error>) in
switch result {
case let .success(geolocation):
completion(geolocation, nil)
case let .failure(error):
completion(nil, error)
}
}
}
从我的角度调用这个方法:
struct MoonPhaseView: View {
getMoonTimes(){geolocation, error in
guard let geolocation = geolocation else {
print("error:", error ?? "nil")
return
}
}
...
...
...
【问题讨论】: