【问题标题】:Unable to extract data from Observable Object无法从可观察对象中提取数据
【发布时间】:2020-01-16 23:51:48
【问题描述】:

我正在尝试显示来自观察对象的数据。

最初我试图保持简单,只显示结构的一个成员:'base'(值:“stations”)。

struct Sample: Codable {
    let coord: Coord
    let weather: [Weather]
    let base: String
    let main: Main
    let visibility: Int
    let wind: Wind
    let clouds: Clouds
    let dt: Double
//    let sys: Sys
    let id: Int
    let name: String
//    let cod: Int
}

我用“?”做了一些防御性编码但我得到以下编译器错误:

所以我替换了'?用'!',知道我应该有一些数据。

我发现这令人沮丧,来自命令式范式背景。
我做错了什么?

这是数据转储:

示例(坐标:DataTaskPubTab.Coord(经度:-0.13,纬度:51.51),天气: [DataTaskPubTab.Weather(id: 300, main: "细雨", description: "光 强度毛毛雨")],基地:“车站”,主要: DataTaskPubTab.Main(温度:280.32,压力:1012,湿度:81, tempMin:279.15,tempMax:281.15),能见度:10000,风: DataTaskPubTab.Wind(速度:4.1,度:80),云: DataTaskPubTab.Clouds(all: 90), dt: 1485789600.0, id: 2643743, name: “伦敦”)

这是 Observable 对象:

class StandardWeatherReportLoader: ObservableObject {
    @Published var networkMessage: String?
    @Published var hasAlert = false
    @Published var weatherReport: Sample?
    @Published var hasReport = false

    func doStandard() {
        let url = EndPoint.weather.path()
        var request = URLRequest(url: EndPoint.weather.path()!)
        request.httpMethod = "GET"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")

        let task = URLSession.shared.dataTask(with: url!) { (data: Data?, _: URLResponse?, error: Error?) -> Void in
            DispatchQueue.main.async {
                guard error == nil else {
                    self.networkMessage = error?.localizedDescription
                    self.hasAlert = true
                    return
                }

                do {
                    let decoder = JSONDecoder()
                    decoder.keyDecodingStrategy = .convertFromSnakeCase
                    let result = try decoder.decode(Sample.self, from: data!)
                    self.weatherReport = result
                    self.hasReport = true
                    print(result)
                } catch let error as NSError {
                    print(error)
                }
            }
        }
        task.resume()
    }
}

【问题讨论】:

    标签: ios swiftui combine


    【解决方案1】:

    显然这有效:

    struct StandardWeatherView: View {
        @EnvironmentObject var settings: Settings
        @ObservedObject var standardWeatherReportLoader = StandardWeatherReportLoader()
    
        init() {
            self.standardWeatherReportLoader.doStandard()
        }
    
        var body: some View {
            NavigationView {
                ZStack {
                    Color("FernGreen").edgesIgnoringSafeArea(.all)
                    VStack {
                        if standardWeatherReportLoader.weatherReport?.base == nil {
                            Text("Sorry, NO data.")
                        } else {
                            Text(standardWeatherReportLoader.weatherReport!.base)
                        }
    
                        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
                    }
                    .navigationBarTitle(Text("Weather Report"), displayMode: .inline)
                }.alert(isPresented: $standardWeatherReportLoader.hasAlert, content: { () -> Alert in
                    Alert(title: Text(verbatim: standardWeatherReportLoader.networkMessage!))
                })
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      很可能在第一次呈现视图时 Web 服务数据还不可用。所以你不应该用! 强制解开这个值。如果你想在这两种情况下都创建一个Text() 元素,你可以简单地使用?? 操作(参见Swift 语言文档中的Nil-Coalescing Operator):

      Text(standardWeatherReportLoader.weatherReport?.base ?? "Sorry, NO data.")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-16
        • 2020-12-01
        • 2018-04-11
        • 1970-01-01
        • 2019-09-09
        • 2017-07-12
        相关资源
        最近更新 更多