【问题标题】:Issues Switching From UIKit to SwiftUI and Passing API Data to the View从 UIKit 切换到 SwiftUI 并将 API 数据传递到视图的问题
【发布时间】:2021-01-15 16:22:09
【问题描述】:

我刚刚将我的应用程序转换为 SwiftUI 框架。前端工作得很好,但我遇到了一个大问题 - 我无法弄清楚如何从用户 UITextField 条目中获取我的数据并更新我的视图。这个项目有很多代码,但我已经将它压缩成几个文件,并且将只共享一部分,因为应用程序的其他部分以类似的方式构建。我真的很感激任何人都可以提供的帮助。我打算用基于解码的 API 调用数据的变量替换 METARView 文本标签中的许多字符串。

前端:ContentView()

//
//  ContentView.swift
//  Aviate
//
//  Created by Grayson Bertaina on 9/27/20.
//
import Combine
import SwiftUI
import Foundation

class Query: ObservableObject {
    var didChange = PassthroughSubject<Void, Never>()
}

struct ContentView: View {
    
    
    init() {
        UITableView.appearance().backgroundColor = .clear
    }
    
    
    @State var stationQuery: String = ""

    
    
    var body: some View {

            NavigationView{
           
                VStack {
                    Text("The App for GA Pilots")
                    Spacer()
                    
                    VStack(alignment: .leading){
                        Text("News")
                            .background(Color.blue)
                            .font(.title)
                            .padding()
                            
                        Text("Aviate now supports chart lookup functionality!")
                            .padding()
                            
                            
                        
                    }
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .padding()
                    
                    
                    
                        
                    VStack(alignment: .leading) {
                        
                        Text("Favorite Airports")
                            .font(.title)
                            .padding()
                        
                        
                        List {
                            
                            
                            Section(header: Text("Favorite Airports")) {
                            NavigationLink(destination: METARView(search: stationQuery)) {
                                Text("Airport 1")
                            }
                            }
                            
                            Section(header: Text("Nearby Stations")) {
                            NavigationLink(destination: METARView(search: stationQuery)) {
                                Text("Airport 1")
                                }
                            }
                        }
                    
                        }
                    

                    Spacer()
                    
                    
                    HStack{
                        TextField("Enter ICAO", text: $stationQuery)
                            .padding()
                            .border(Color.black)
                            
                        NavigationLink(destination: METARView(search: stationQuery)) {
                            Text("Search")
                            

                        }
                        .padding()
                        .background(Color.blue)
                        .foregroundColor(.white)
                    }
                    .padding()
                    
                    
                    
                }
                .navigationBarTitle("Aviate Home")
                
           
    }
        
    }
    
    
    
}





struct METARView: View {

    
    @State var weatherManager = WeatherManager()
       
       init(search: String) {
           self.weatherManager.fetchWeather(stationICAO: search)
       }

    var body: some View {
        
        
        
        ScrollView{
            
            METARReport(model: weatherManager.weather)
            MapView()
                .frame(height: 200)
                .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
            
            METARTitleView()
                .frame(height: 250)
               
            METARReport()
                
            Spacer()
        }
        .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
    }
    
    
}

struct TAFView: View {

    var search: String

    var body: some View {

        ScrollView{
            MapView()
                .frame(height: 200)
                .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
            METARTitleView()
                .frame(height: 250)
               
            TAFReport()
                
           
        }
        .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
    }
}


struct AirportView: View {

    var search: String

    var body: some View {

        ScrollView{
            MapView()
                .frame(height: 200)
                .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
            
               
            AirportReport()
                
           
        }
        .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .previewDevice("iPhone 11")
        
    }
}



final class DataModel: ObservableObject {
  static let shared = DataModel()
  @Published var observedString = "" {
    didSet {
      //RUNS SUCCESSFULLY
      print("Observed string changed to \(observedString)")
    }
  }
}

这是 METARView() 的一部分,需要了解数据的去向 - 它将显示提取的数据。

METARReport()

//
//  METARReport.swift
//  Aviate
//
//  Created by Grayson Bertaina on 9/29/20.
//

import SwiftUI
import Foundation


var weatherManager = WeatherManager()



struct METARReport: View {
    

    
    var body: some View {
        ScrollView {
            VStack{
            HStack{
                Text("METAR Report")
                    .font(.title)
                    
                Spacer()
                Text("Time: " + "")
                    .font(.headline)
            }
            
            .padding()
            
            HStack{
                Text("Flight Rules")
                  
                Spacer()
                Text("VFR")
                    .padding()
                    .background(Color.green)
                 
            }
            .padding()
            .font(.headline)
            
                HStack(spacing: 20){
                    VStack(alignment: .leading){
                        Text("Visibility")
                          
                        Spacer()
                        Text("10" + " SM")
                            
                           
                    }
                    
                    
                    VStack(alignment: .leading){
                        Text("Temperature")
                          
                        Spacer()
                        Text("25" + " °C")
                         
                           
                    }
                    
                    VStack(alignment: .leading){
                        Text("Dew Point")
                          
                        Spacer()
                        Text("25" + " °C")
                           
                           
                    }
                 
            }
            .padding()
            .font(.headline)
                
                VStack(alignment: .center){
                    Text("Clouds")
                        .font(.headline)
                        .padding()
                        
                    HStack() {
                        Text("Few")
                        Spacer()
                    
                        Text("1200")
                    }
                    .padding()
                    HStack() {
                        Text("Few")
                        Spacer()
                    
                        Text("1200")
                    }
                    .padding()
                    HStack() {
                        Text("Few")
                        Spacer()
                    
                        Text("1200")
                    }
                    .padding()
                }
                .font(.headline)
            
                HStack{
                    Text("Altimeter")
                      
                    Spacer()
                    Text("29.92")
                     
                }
                .font(.headline)
                .padding()
                
                VStack{
                    Text("Wind")
                    HStack{
                        Text("5" + "kt")
                        Text("G")
                        Text("12" + "kt")
                        Text("From")
                        Text("310" + "°")
                        
                    }
                    .padding()
                    
                }
                .font(.headline)
            
                HStack {
                    Text("Special Wx")
                    Spacer()
                    Text("+RA")
                }
                .padding()
                .font(.headline)
                
                VStack {
                    Text("Remarks")
                    Spacer()
                    Text("No Remarks")
                }
                .padding()
                .font(.headline)
        }
    }
    }
}

struct METARReport_Previews: PreviewProvider {
    static var previews: some View {
        METARReport()
    }
}

后端:WeatherStorage(包含 WeatherData、WeatherModel 和 WeatherManager 以及 API 调用)

struct WeatherData: Codable {
   
    let flight_rules: String?
    let remarks: String?
    let wind_speed: WindSpeed?
    let wind_gust: WindGust?
    let wind_direction: WindDirection?
    let visibility: Visibility?
    let time: Time?
    let station: String?
    let temperature: Temperature?
    let raw: String?
    let clouds: [Clouds?]
    let wx_codes: [Wxcodes?]
}

struct Clouds: Codable {
    let type: String
    let altitude: Int
}

struct Time: Codable {
    let repr: String
}

struct WindSpeed: Codable {
    let value: Int
}

struct WindGust: Codable {
    let value: Int
}

struct WindDirection: Codable {
    let repr: String
}

struct Visibility: Codable {
    let repr: String
}

struct Remarks: Codable {
    let remarks: String
}

struct Altimeter: Codable {
    let repr: String?
    let spoken: String?
}

struct Temperature: Codable {
    let repr: String
}

struct Dewpoint: Codable {
    let repr: String
}

struct Wxcodes: Codable {
    let value: String
}

// WeatherModel

//
//  WeatherModel.swift
//  AvWx Pro
//
//  Created by Grayson Bertaina on 9/22/20.
//

import Foundation

struct WeatherModel {
    let reportingStation: String
    let windGust: Int
    let windSpeed: Int
    let windDirection: String
    let visibility: String
    let flightRules: String
    let time: String
    let remarks: String
    let temperature: String
    let dewpoint: String
    let rawMETAR: String
    let lowestCloudsType: String
    let lowestCloudsAlt: Int
    let middleCloudsType: String
    let middleCloudsAlt: Int
    let highestCloudsType: String
    let highestCloudsAlt: Int
    let firstWxCode: String
    
    var windGustString: String {
        return String(format: "%u" + "kt", windGust)
    }
    
    
    var windSpeedString: String {
        return String(format: "%u" + "kt", windSpeed)
    }
    
    
    var visUnits: String {
        return visibility + " SM"
    }
    
    var degUnits: String {
        return windDirection + "°"
    }
    
    var tempUnits: String {
        return temperature + "°C"
    }
    
    var dewUnits: String {
        return dewpoint + "°C"
    }
    
    var altToString1: String {
        return String(format: "%u" + "00 ft", lowestCloudsAlt)
    }
    
    var altToString2: String {
        return String(format: "%u" + "00 ft", middleCloudsAlt)
    }
    
    var altToString3: String {
        return String(format: "%u" + "00 ft", highestCloudsAlt)
    }
    

    
    var flightConditions: String {
        switch flightRules {
        case "VFR":
            return "green"
        case "MVFR":
            return "blue"
        case "IFR":
            return "red"
        case "LIFR":
            return "purple"
        default:
            return "gray"
        
        }
    }
}

    private func parseJSON(_ weatherData: Data) -> WeatherModel? {
        do {
            let decoder = JSONDecoder()
            let decodedData = try decoder.decode(WeatherData.self, from: weatherData)

            
            let clouds = decodedData.clouds
            let wxcodes = decodedData.wx_codes
            let reportingStationVar = decodedData.station ?? "N/A"
            let windGustValue = decodedData.wind_gust?.value ?? 0
            let windSpeedValue = decodedData.wind_speed?.value ?? 0
            let windDirectionValue = decodedData.wind_direction?.repr ?? "N/A"
            let visibilityValue = decodedData.visibility?.repr ?? "N/A"
            let flightRulesValue = decodedData.flight_rules ?? "N/A"
            let timeReportedMETAR = decodedData.time?.repr ?? "N/A"
            let remarksReportedMETAR = decodedData.remarks ?? "N/A"
            let tempMETAR = decodedData.temperature?.repr ?? "No Data"
            let rawMETARData = decodedData.raw ?? "N/A"
            let lowCloudsType = (clouds.count > 0 ? clouds[0]?.type : nil) ?? "N/A"
            let midCloudsType = (clouds.count > 1 ? clouds[1]?.type : nil) ?? "N/A"
            let highCloudsType = (clouds.count > 2 ? clouds[2]?.type : nil) ?? "N/A"
            let lowCloudsAlt = (clouds.count > 0 ? clouds[0]?.altitude : nil) ?? 0
            let midCloudsAlt = (clouds.count > 1 ? clouds[1]?.altitude : nil) ?? 0
            let highCloudsAlt = (clouds.count > 2 ? clouds[2]?.altitude : nil) ?? 0
            let firstWxCode1 = (wxcodes.count > 0 ? wxcodes[0]?.value : "N/A") ?? "N/A"
            
            let weather = WeatherModel(reportingStation: reportingStationVar, windGust: windGustValue, windSpeed: windSpeedValue, windDirection: windDirectionValue, visibility: visibilityValue, flightRules: flightRulesValue, time: timeReportedMETAR, remarks: remarksReportedMETAR, temperature: tempMETAR, dewpoint: rawMETARData, rawMETAR: rawMETARData, lowestCloudsType: lowCloudsType, lowestCloudsAlt: lowCloudsAlt, middleCloudsType: midCloudsType, middleCloudsAlt: midCloudsAlt, highestCloudsType: highCloudsType, highestCloudsAlt: highCloudsAlt, firstWxCode: firstWxCode1)
            
            return weather
            
        } catch {
            print(error)
            return nil
        }
    }

你会注意到有一些无用的函数,比如在我的 ContentView 顶部尝试 fetchWeather。我正在尝试各种方法来获取要提取的数据,但不知道在哪里放置所需的数据:

  • fetchWeather 函数,以及要初始化的内容
  • 如何更新视图并初始化 WeatherModel 或 WeatherManager 以获取该数据。

我是 Swift 新手,所以如果我的问题的任何部分含糊不清,我深表歉意。我肯定有点过头了!感谢您的帮助,祝您有美好的一天。

添加:

//
//  WeatherData.swift
//  SwitUIAppExample
//
//  Created by mac on 30/09/2020.
//  Copyright © 2020 Kamran. All rights reserved.
//

//
//  WeatherData.swift
//  AvWx Pro
//
//  Created by Grayson Bertaina on 9/21/20.
//

import Foundation

struct WeatherData: Codable {
   
    
    let clouds: [Clouds?]
    let flight_rules: String?
    let remarks: String?
    let wind_speed: WindSpeed?
    let wind_gust: WindGust?
    let wind_direction: WindDirection?
    let visibility: Visibility?
    let time: Time?
    let station: String?
    let altimeter: Altimeter?
    let temperature: Temperature?
    let dewpoint: Dewpoint?
    let wx_codes: [Wxcodes?]
    let raw: String?
}



struct Clouds: Codable {
    let type: String
    let altitude: Int
}

struct Time: Codable {
    let repr: String
}

struct WindSpeed: Codable {
    let value: Int
}

struct WindGust: Codable {
    let value: Int
}

struct WindDirection: Codable {
    let repr: String
}

struct Visibility: Codable {
    let repr: String
}

struct Remarks: Codable {
    let remarks: String
}

struct Altimeter: Codable {
    let value: Double
}

struct Temperature: Codable {
    let repr: String
}

struct Dewpoint: Codable {
    let repr: String
}

struct Wxcodes: Codable {
    let value: String
}


// WeatherModel

//
//  WeatherModel.swift
//  AvWx Pro
//
//  Created by Grayson Bertaina on 9/22/20.
//

import Foundation

struct WeatherModel {
    
    
    let lowestCloudsType: String
    let lowestCloudsAlt: Int
    let middleCloudsType: String
    let middleCloudsAlt: Int
    let highestCloudsType: String
    let highestCloudsAlt: Int
    let reportingStation: String
    let windGust: Int
    let windSpeed: Int
    let windDirection: String
    let visibility: String
    let flightRules: String
    let time: String
    let remarks: String
    let altimeter: Double
    let temperature: String
    let dewpoint: String
    let firstWxCode: String
    let rawMETAR: String
    
    var altToString1: String {
        return String(format: "%u" + "00 ft", lowestCloudsAlt)
    }
    
    var altToString2: String {
        return String(format: "%u" + "00 ft", middleCloudsAlt)
    }
    
    var altToString3: String {
        return String(format: "%u" + "00 ft", highestCloudsAlt)
    }
    
    var windGustString: String {
        return String(format: "%u" + "kt", windGust)
    }
    
    
    var windSpeedString: String {
        return String(format: "%u" + "kt", windSpeed)
    }
    
    var altimeterString: String {
        return String(format: "%.2f" + " inHg", altimeter as CVarArg)
    }
    
    var visUnits: String {
        return visibility + " SM"
    }
    
    var degUnits: String {
        return windDirection + "°"
    }
    
    var tempUnits: String {
        return temperature + "°C"
    }
    
    var dewUnits: String {
        return dewpoint + "°C"
    }

    
    var flightConditions: String {
        switch flightRules {
        case "VFR":
            return "green"
        case "MVFR":
            return "blue"
        case "IFR":
            return "red"
        case "LIFR":
            return "purple"
        default:
            return "gray"
        
        }
    }
}



// WeatherManager

//
//  WeatherManager.swift
//  AvWx Pro
//
//  Created by Grayson Bertaina on 9/21/20.
//

import Foundation

class WeatherManager: ObservableObject {
    
    @Published var weater: WeatherModel?
    
    let weatherURL = "https://avwx.rest/api/metar/"
    

    func fetchWeather (stationICAO: String) {
        let urlString = "\(weatherURL)\(stationICAO)?token=OVi45FiTDo1LmyodShfOfoizNe5m9wyuO6Mkc95AN-c"
        performRequest(with: urlString)
    }
    
    func performRequest (with urlString: String) {
        if let url = URL(string: urlString) {
            let session = URLSession(configuration: .default)
                
            
            let task = session.dataTask(with: url) { (data, response, error) in
                if error != nil {
                    print(error)
                    return
                }
                
                if let safeData = data {
                    self.weater = self.parseJSON(safeData)
                }
            }
            
            task.resume()
            print(urlString)
            
            
            }
        }
    
   
    private func parseJSON(_ weatherData: Data) -> WeatherModel? {
        do {
            let decoder = JSONDecoder()
            let decodedData = try decoder.decode(WeatherData.self, from: weatherData)

            let clouds = decodedData.clouds
            let wxcodes = decodedData.wx_codes
            let lowCloudsType = (clouds.count > 0 ? clouds[0]?.type : nil) ?? "N/A"
            let midCloudsType = (clouds.count > 1 ? clouds[1]?.type : nil) ?? "N/A"
            let highCloudsType = (clouds.count > 2 ? clouds[2]?.type : nil) ?? "N/A"
            let lowCloudsAlt = (clouds.count > 0 ? clouds[0]?.altitude : nil) ?? 0
            let midCloudsAlt = (clouds.count > 1 ? clouds[1]?.altitude : nil) ?? 0
            let highCloudsAlt = (clouds.count > 2 ? clouds[2]?.altitude : nil) ?? 0
            let reportingStationVar = decodedData.station ?? "N/A"
            let windGustValue = decodedData.wind_gust?.value ?? 0
            let windSpeedValue = decodedData.wind_speed?.value ?? 0
            let windDirectionValue = decodedData.wind_direction?.repr ?? "N/A"
            let visibilityValue = decodedData.visibility?.repr ?? "N/A"
            let flightRulesValue = decodedData.flight_rules ?? "N/A"
            let timeReportedMETAR = decodedData.time?.repr ?? "N/A"
            let remarksReportedMETAR = decodedData.remarks ?? "N/A"
            let altimeterMETAR = decodedData.altimeter?.value ?? 0
            let tempMETAR = decodedData.temperature?.repr ?? "No Data"
            let dewMETAR = decodedData.dewpoint?.repr ?? "No Data"
            let firstWxCode1 = (wxcodes.count > 0 ? wxcodes[0]?.value : "N/A") ?? "N/A"
            let rawMETARData = decodedData.raw ?? "N/A"
            
            let weather = WeatherModel(lowestCloudsType: lowCloudsType , lowestCloudsAlt: lowCloudsAlt, middleCloudsType: midCloudsType , middleCloudsAlt: midCloudsAlt, highestCloudsType: highCloudsType , highestCloudsAlt: highCloudsAlt, reportingStation: reportingStationVar, windGust: windGustValue, windSpeed: windSpeedValue, windDirection: windDirectionValue, visibility: visibilityValue, flightRules: flightRulesValue, time: timeReportedMETAR, remarks: remarksReportedMETAR, altimeter: altimeterMETAR, temperature: tempMETAR, dewpoint: dewMETAR, firstWxCode: firstWxCode1, rawMETAR: rawMETARData)
            return weather
            
        } catch {
            print(error)
            return nil
        }
    }
    
    

}

【问题讨论】:

  • 感谢这些链接。我正在苦苦挣扎,因为我试图从三个 API 源中提取数据,而 List API 拉取模型对我没有多大帮助的原因是因为我正在提取不同类型的数据。例如,在一次拉动中,我可能有 Doubles、Strings、Int 和 Arrays,它们具有不同的键来引用每个部分。
  • 我尝试删除 MapView/AirportView 等进行编译并使其能够解决问题。请检查下面的答案。希望它有助于修复它。
  • 请检查上传的代码here 是否有修复。请参阅聊天以了解更多详情。

标签: ios swift xcode api swiftui


【解决方案1】:

你需要引入一些改变如下,

WeatherManager改为class,符合ObservableObject,并引入如下天气模型,

class WeatherManager: ObservableObject {
    
    @Published var weather: WeatherModel?
    
}

WeatherManager 的其余部分相同,只是您需要在 performRequest 方法中解析后设置上述属性,如下所示,

if let safeData = data {
    self.weather = self.parseJSON(safeData)
}

现在通过引入var model: WeatherModel?来更改METARReport,并将所有标签设置为如下所示的时间,

struct METARReport: View {
    
    var model: WeatherModel?
    
    var body: some View {
        ScrollView {
            VStack{
            HStack{
                Text("METAR Report")
                    .font(.title)
                    
                Spacer()
                Text("Time: " + (self.model?.time ?? ""))
                    .font(.headline)
            }

.....
}

最后只更新METARView如下,

struct METARView: View {

    @State var weatherManager = WeatherManager()
    
    init(search: String) {
        self.weatherManager.fetchWeather(stationICAO: search)
    }
    
    var body: some View {
    
        ScrollView{
            // ...
            METARReport(model: weatherManager.weather)
                
            Spacer()
        }
        .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
    }
}

注意:您的代码中也存在一些解析问题,因此我使用以下模型使其工作。

struct WeatherData: Codable {
   
    let flight_rules: String?
    let remarks: String?
    let wind_speed: WindSpeed?
    let wind_gust: WindGust?
    let wind_direction: WindDirection?
    let visibility: Visibility?
    let time: Time?
    let station: String?
    let temperature: Temperature?
    let raw: String?
}

struct Clouds: Codable {
    let type: String
    let altitude: Int
}

struct Time: Codable {
    let repr: String
}

struct WindSpeed: Codable {
    let value: Int
}

struct WindGust: Codable {
    let value: Int
}

struct WindDirection: Codable {
    let repr: String
}

struct Visibility: Codable {
    let repr: String
}

struct Remarks: Codable {
    let remarks: String
}

struct Altimeter: Codable {
    let repr: String?
    let spoken: String?
}

struct Temperature: Codable {
    let repr: String
}

struct Dewpoint: Codable {
    let repr: String
}

struct Wxcodes: Codable {
    let value: String
}

// WeatherModel

//
//  WeatherModel.swift
//  AvWx Pro
//
//  Created by Grayson Bertaina on 9/22/20.
//

import Foundation

struct WeatherModel {
    let reportingStation: String
    let windGust: Int
    let windSpeed: Int
    let windDirection: String
    let visibility: String
    let flightRules: String
    let time: String
    let remarks: String
    let temperature: String
    let dewpoint: String
    let rawMETAR: String
    
    var windGustString: String {
        return String(format: "%u" + "kt", windGust)
    }
    
    
    var windSpeedString: String {
        return String(format: "%u" + "kt", windSpeed)
    }
    
    
    var visUnits: String {
        return visibility + " SM"
    }
    
    var degUnits: String {
        return windDirection + "°"
    }
    
    var tempUnits: String {
        return temperature + "°C"
    }
    
    var dewUnits: String {
        return dewpoint + "°C"
    }

    
    var flightConditions: String {
        switch flightRules {
        case "VFR":
            return "green"
        case "MVFR":
            return "blue"
        case "IFR":
            return "red"
        case "LIFR":
            return "purple"
        default:
            return "gray"
        
        }
    }
}

    private func parseJSON(_ weatherData: Data) -> WeatherModel? {
        do {
            let decoder = JSONDecoder()
            let decodedData = try decoder.decode(WeatherData.self, from: weatherData)

            let reportingStationVar = decodedData.station ?? "N/A"
            let windGustValue = decodedData.wind_gust?.value ?? 0
            let windSpeedValue = decodedData.wind_speed?.value ?? 0
            let windDirectionValue = decodedData.wind_direction?.repr ?? "N/A"
            let visibilityValue = decodedData.visibility?.repr ?? "N/A"
            let flightRulesValue = decodedData.flight_rules ?? "N/A"
            let timeReportedMETAR = decodedData.time?.repr ?? "N/A"
            let remarksReportedMETAR = decodedData.remarks ?? "N/A"
            let tempMETAR = decodedData.temperature?.repr ?? "No Data"
            let rawMETARData = decodedData.raw ?? "N/A"
            
            let weather = WeatherModel(reportingStation: reportingStationVar, windGust: windGustValue, windSpeed: windSpeedValue, windDirection: windDirectionValue, visibility: visibilityValue, flightRules: flightRulesValue, time: timeReportedMETAR, remarks: remarksReportedMETAR, temperature: tempMETAR, dewpoint: rawMETARData, rawMETAR: rawMETARData)
            
            return weather
            
        } catch {
            print(error)
            return nil
        }
    }

【讨论】:

  • 这是一个很好的答案!我将暂时标记为正确 - 但在 METARView 视图开始时,@State var weatherManager = WeatherManager()var search: String 下方出现错误。我在哪里可以初始化缺失的属性?
  • METARView 中删除var search: String。只需将其传递给fetchWeather 内的init 即可。
  • 错误仍然存​​在:在范围内找不到“WeatherManager”
  • 请清理 + 重新构建。或者重启 Xcode。如果有帮助,请告诉我。
  • 仍然没有解决方案,我将我的新 ContentView 更新为帖子。就在上面那个旧的地方。
猜你喜欢
  • 2021-05-18
  • 1970-01-01
  • 1970-01-01
  • 2020-10-08
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 1970-01-01
  • 2021-01-09
相关资源
最近更新 更多