如何构造值以使所有视图都可以在 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 中强制转换字符串值以使应用程序崩溃

是否可以使我的视图中心等于(0,0)?

用户可以更改 Chrome 中 Redux/Mobx 的值以访问受限视图吗?

在 Django 视图中检索 Select2 多值以在后端使用

如何在jira中动态或使用插件添加新值以选择列表字段

如何在所有项目中收集 SettingKey 的所有值以用于 sbt 插件?