"Out of index" SwiftUI ContentView 中的错误但不在函数中

"Out of index" error within SwiftUI ContentView but not in function

我正在创建一个天气应用程序。我使用 API (OpenWeatherApp) 来获取我的数据。我将数据加载到类型为 struct WeatherJSON.

的数组 weatherArray

我可以使用 ForEach 循环成功访问数据,但是当我尝试使用 array[index] 直接访问特定数据时,出现以下错误:Thread 1: Fatal error: Index out of range

这是我正在使用的顶级结构:

// holds all data from the JSON request
struct WeatherJSON: Codable {
    var coord: Coord            // coordinate struct
    var weather: [Weather]      // array of Weather struct
    var base: String            // "internal parameter..?"
    var main: Main              // main struct (contains the juicy data)
    var visibility: Int         // visibility number
    var wind: Wind              // wind struct
    var clouds: Clouds          // clouds struct
    var dt: Int                 // time of data calculation, unix, UTC
    var sys: Sys                // internal parameer
    var timezone, id: Int       // timezone
    var name: String            // city namme
    var cod: Int                // another internal parameter (..?)
} 

我的内容视图:

struct ContentView: View {
    
    @State private var weatherArray: [WeatherJSON] = []
//    @State private var weatherArray: [Weather] = []
    
    var body: some View {
        NavigationView {
            VStack {
                Text("\(weatherArray[0].name)") // <---- This doesn't work
                List {
//                    Text("Current conditions: \(weatherArray[0].description)")
                    
//                    ForEach(weatherArray, id: \.self) { result in
//                        Section(header:Text("Address")) {
//                            Text("Current conditions: \(result.main)")
//                                .font(.headline)
//                                .bold()
//                            Text("Weather description: \(result.description)")
//                                .font(.body)
//                        }
//                    }
                }
                .navigationTitle("Weather")
            }
        }
        .task { await handleData() }
    }
    
    func handleData() async {
        
        guard let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=Seattle&appid={APIKEY}") else {
            print("This URL does not work!")
            return
        }
        
        let decoder = JSONDecoder()
        
        do {
            let (weatherData, _) = try await URLSession.shared.data(from: url)
            if let weatherObj = try? decoder.decode(WeatherJSON.self, from: weatherData) {
                weatherArray.append(weatherObj)// = weatherObj.weather
                print(weatherArray[0]) // <--- This works?
            }

        } catch {
            print("Did not work :(")
        }
    } ```

您的视图正在加载数据之前访问 weatherArray。您需要考虑一个可能为空的数组以避免崩溃。

变化:

Text("\(weatherArray[0].name)") // <---- This doesn't work

收件人:

Text("\(weatherArray.first?.name ?? "")")

尝试使用此示例代码将天气数据导入您的模型并在您的视图中使用它:

public struct Weather: Identifiable, Codable {
    public let id: Int
    public let main, description, icon: String
}

struct Coord: Codable {
    var lon: Double
    var lat: Double
}

// holds all data from the JSON request
struct WeatherJSON: Codable {
    var coord: Coord             // coordinate struct
    var weather: [Weather]       // array of Weather struct
    var base: String             // "internal parameter..?"
    var main: Main              // main struct (contains the juicy data)
    var visibility: Int         // visibility number
    var wind: Wind              // wind struct
    var clouds: Clouds          // clouds struct
    var dt: Int                  // time of data calculation, unix, UTC
    var sys: Sys                // internal parameer
    var timezone, id: Int        // timezone
    var name: String             // city namme
    var cod: Int                 // another internal parameter (..?)
}


struct ContentView: View {
    
    @State private var city: WeatherJSON?
    
    var body: some View {
        NavigationView {
            VStack {
                Text("\(city?.name ?? "no name")")
                List {
                    ForEach(city?.weather ?? []) { weather in
                        Section(header:Text("Address")) {
                            Text("Current conditions: \(weather.main)")
                                .font(.headline)
                                .bold()
                            Text("Weather description: \(weather.description)")
                                .font(.body)
                        }
                    }
                }
                .navigationTitle("Weather")
            }
        }
        .task { await handleData() }
    }
    
    func handleData() async {
        guard let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=Seattle&appid={apikey}") else {
            print("This URL does not work!")
            return
        }
        do {
            let (weatherData, _) = try await URLSession.shared.data(from: url)
            city = try JSONDecoder().decode(WeatherJSON.self, from: weatherData)
            print(city)
        } catch {
            print("error: \(error)")
        }
    }
}