如何构造值以使所有视图都可以在 Swift/SwiftUI 中访问其值?
Posted
技术标签:
【中文标题】如何构造值以使所有视图都可以在 Swift/SwiftUI 中访问其值?【英文标题】:How to struct's value such that all views can access its values in Swift/SwiftUI? 【发布时间】: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
...
...
...
【问题讨论】:
【参考方案1】:IMO 最好返回结果并处理错误。请注意,您分配了不应分配的相同名称结果。将其更改为case let .success(geolocation)
。您需要为您的方法添加一个完成处理程序,因为请求异步运行并返回一个选项坐标和一个可选错误:
请注意,我不确定您是否只想使用您的方法获取位置(坐标)或整个结构。但重点是为您的方法添加一个完成处理程序并传递您想要的属性或整个结构。
func getMoonTimes(for queryItems: [URLQueryItem], completion: @escaping (Coordinates?,Error?) -> Void)
urlComponents.queryItems = queryItems
urlComponents.url?.getResult (result: Result<IPGeolocation, Error>) in
switch result
case let .success(geolocation):
completion(geolocation.location, nil)
case let .failure(error):
completion(nil, error)
用法:
getMoonTimes(for: queryItems) location, error in
guard let location = location else
print("error:", error ?? "nil")
return
print("Location:", location)
print("Latitude:", location.latitude)
print("Longitude:", location.longitude)
【讨论】:
非常有帮助,谢谢。我想返回整个 IPGeolocation 结构,而不仅仅是坐标。我目前在 getMoonTimes 方法中创建 queryItems 并且不传递它们。我使用上面的完成闭包将 goelocation 作为 IPGeolocation 结构返回。我的理解是现在我应该能够在没有 for: queryItems 的情况下调用上述函数并分配给一个变量以在我的视图中使用。在 getMoonTimes 的第一行中使用“位置”时,它超出了范围,因为它没有被声明对吗?我将编辑以上内容以反映我所做的更改以上是关于如何构造值以使所有视图都可以在 Swift/SwiftUI 中访问其值?的主要内容,如果未能解决你的问题,请参考以下文章
在 NSDictionary 中强制转换字符串值以使应用程序崩溃
用户可以更改 Chrome 中 Redux/Mobx 的值以访问受限视图吗?