为啥我不能访问这个数组 ForEach 循环中的数据? SwiftUI

Posted

技术标签:

【中文标题】为啥我不能访问这个数组 ForEach 循环中的数据? SwiftUI【英文标题】:Why cannot I not access the data in this array ForEach loop? SwiftUI为什么我不能访问这个数组 ForEach 循环中的数据? SwiftUI 【发布时间】:2019-11-30 15:39:13 【问题描述】:

我在这个问题上遇到了一些困难。由于某种原因,ForEach 循环不允许我使用“天气”对象中的数据。我之前已经这样做了,我可以放置 weather.main.rTemp 并从对象中获取值,但现在我收到一个错误,说这不存在,但是没有任何改变?它在 Xcode 自动填充中建议的唯一选项是 weather.self (这也不起作用或有帮助)

我迷路了,请帮帮我。

我的主要观点:

    import SwiftUI

struct MainForecastView: View 

    @ObservedObject var networkingManager: NetworkingManager

    var body: some View 

        VStack 
            // Text("Weather Forecast")
              //  .font(.headline)
               // .padding(.bottom, 25.0)

            HStack(alignment: .bottom) 
                VStack(alignment: .leading) 
                    Text("Today")
                        .font(.largeTitle)
                        .fontWeight(.medium)
                    Text(self.getDateToday())
                        .font(.subheadline)
                
                Image(systemName: "sun.min.fill")
                .font(.system(size: 36))
                .foregroundColor(Color.yellow)
                    .padding()
                Spacer()
                VStack 
                    Text("12°")
                        .font(.system(size:48))
                        .fontWeight(.medium)
                        .multilineTextAlignment(.trailing)
                    Text("Sydney, AU")
                        .multilineTextAlignment(.trailing)
                
            
            .padding()

            HStack 
                Text("Upcoming Forecast")
                    .font(.headline)
                    .multilineTextAlignment(.leading)
                    .padding(.top)
                Spacer()
            .padding(.leading, 10.0)

            ScrollView(.horizontal, content: 
                HStack(spacing: 5) 
                    ForEach(networkingManager.weatherList, id: \.dt)  weather in
                        CardView(forecastTime: "12PM", forecastTemp: self.networkingManager.weatherList[0].main.rTemp)

                    .padding(.vertical)
                
            )
            VStack 
                HStack 
                    Text("Chance of Showers")
                        .font(.headline)
                    Spacer()
                .padding(.leading, 10.0)
                HStack 
                    Image(systemName: "cloud.rain.fill")
                        .font(.system(size: 28))
                    Text("Low Chance")
                        .font(.title)
                        .padding()
                .padding(.leading, 10.0)
            
            Spacer()
        
        .onAppear()
            self.networkingManager.load()
        
        .blur(radius: 0)
        .padding()
    
    func getDateToday() -> String 
        let df = DateFormatter()
        df.dateFormat = "MMMM dd"
        let dateToday = df.string(from: Date())
        return dateToday
    


struct MainForecastView_Previews: PreviewProvider 
    static var previews: some View 
        MainForecastView(networkingManager: NetworkingManager())
    

然后到我的网络管理器课程

import Foundation
import SwiftUI
import Combine

class NetworkingManager : ObservableObject 
    @Published var inputCity = "Sydney"
    @Published var weatherList = [WeatherInfoList]()
    var weatherCity = CityInformation(name: "Sydney", country: "AU")

    func load() 
        let apiKey = "ced81d2f91438e7897c4443c4567c205"
        guard let url = URL(string: "https://api.openweathermap.org/data/2.5/forecast?q=\(inputCity)&units=metric&APPID=\(apiKey)") else 
            return
        
        print("City is: \(inputCity)")
        URLSession.shared.dataTask(with: url)  (data, response, err) in
            guard let data = data else  return 
            let weatherInfo = try! JSONDecoder().decode(WeatherAPIResponse.self, from: data)
            DispatchQueue.main.async 
                self.weatherCity = weatherInfo.city
                self.weatherList = weatherInfo.list
            
        .resume()
    

最后是来自 API 的数据模型结构

    import Foundation

struct WeatherAPIResponse: Decodable 
    var list: [WeatherInfoList]
    var city: CityInformation

struct CityInformation: Decodable 
    var name: String
    var country: String

struct WeatherInfoList: Decodable 
    let formatter = DateFormatter()
    var dt: Int
    var main: WeatherMain
    var dtTxt: String
    var date: String 
        formatter.dateFormat = "EEE hh:mm a"
        let cDate = Date.init(timeIntervalSince1970: TimeInterval(dt))
        return formatter.string(from: cDate)
    

    enum CodingKeys: String, CodingKey 
        case dt
        case main
        case dtTxt = "dt_txt"
    


struct WeatherMain: Decodable 
    let temp, tempMin, tempMax: Double
    let pressure, seaLevel, grndLevel, humidity: Int
    let tempKf: Double

    var rTemp: Int 
        return Int(temp)
    
    var rTempMax: Int 
        return Int(tempMax)
    
    var rTempMin: Int 
        return Int(tempMin)
    

    enum CodingKeys: String, CodingKey 
        case temp
        case tempMin = "temp_min"
        case tempMax = "temp_max"
        case pressure
        case seaLevel = "sea_level"
        case grndLevel = "grnd_level"
        case humidity
        case tempKf = "temp_kf"
    


【问题讨论】:

【参考方案1】:

我刚刚尝试了您的代码(我不得不稍微更改它,但它是可编译的)。

试试这个:

很遗憾,您没有向我们展示您的 cardView 实现...也许问题出在哪里?

import SwiftUI
import Foundation
import Combine


struct ContentView: View 

    @ObservedObject var networkingManager: NetworkingManager

    var body: some View 

        VStack 
            // Text("Weather Forecast")
              //  .font(.headline)
               // .padding(.bottom, 25.0)

            HStack(alignment: .bottom) 
                VStack(alignment: .leading) 
                    Text("Today")
                        .font(.largeTitle)
                        .fontWeight(.medium)
                    Text(self.getDateToday())
                        .font(.subheadline)
                
                Image(systemName: "sun.min.fill")
                .font(.system(size: 36))
                .foregroundColor(Color.yellow)
                    .padding()
                Spacer()
                VStack 
                    Text("12°")
                        .font(.system(size:48))
                        .fontWeight(.medium)
                        .multilineTextAlignment(.trailing)
                    Text("Sydney, AU")
                        .multilineTextAlignment(.trailing)
                
            
            .padding()

            HStack 
                Text("Upcoming Forecast")
                    .font(.headline)
                    .multilineTextAlignment(.leading)
                    .padding(.top)
                Spacer()
            .padding(.leading, 10.0)

            ScrollView(.horizontal, content: 
                HStack(spacing: 5) 
                    ForEach(networkingManager.weatherList, id: \.dt)  weather in
           //             CardView(forecastTime: "12PM", forecastTemp: self.networkingManager.weatherList[0].main.rTemp)
                        Text(weather.date)
                    .padding(.vertical)
                
            )
            VStack 
                HStack 
                    Text("Chance of Showers")
                        .font(.headline)
                    Spacer()
                .padding(.leading, 10.0)
                HStack 
                    Image(systemName: "cloud.rain.fill")
                        .font(.system(size: 28))
                    Text("Low Chance")
                        .font(.title)
                        .padding()
                .padding(.leading, 10.0)
            
            Spacer()
        
        .onAppear()
            self.networkingManager.load()
        
        .blur(radius: 0)
        .padding()
    
    func getDateToday() -> String 
        let df = DateFormatter()
        df.dateFormat = "MMMM dd"
        let dateToday = df.string(from: Date())
        return dateToday
    


struct MainForecastView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView(networkingManager: NetworkingManager())
    



class NetworkingManager : ObservableObject 
    @Published var inputCity = "Sydney"
    @Published var weatherList = [WeatherInfoList]()
    var weatherCity = CityInformation(name: "Sydney", country: "AU")

    func load() 
        let apiKey = "ced81d2f91438e7897c4443c4567c205"
        guard let url = URL(string: "https://api.openweathermap.org/data/2.5/forecast?q=\(inputCity)&units=metric&APPID=\(apiKey)") else 
            return
        
        print("City is: \(inputCity)")
        URLSession.shared.dataTask(with: url)  (data, response, err) in
            guard let data = data else  return 
            let weatherInfo = try! JSONDecoder().decode(WeatherAPIResponse.self, from: data)
            DispatchQueue.main.async 
                self.weatherCity = weatherInfo.city
                self.weatherList = weatherInfo.list
            
        .resume()
    


struct WeatherAPIResponse: Decodable 
    var list: [WeatherInfoList]
    var city: CityInformation

struct CityInformation: Decodable 
    var name: String
    var country: String

struct WeatherInfoList: Decodable 
    let formatter = DateFormatter()
    var dt: Int
    var main: WeatherMain
    var dtTxt: String
    var date: String 
        formatter.dateFormat = "EEE hh:mm a"
        let cDate = Date.init(timeIntervalSince1970: TimeInterval(dt))
        return formatter.string(from: cDate)
    

    enum CodingKeys: String, CodingKey 
        case dt
        case main
        case dtTxt = "dt_txt"
    


struct WeatherMain: Decodable 
    let temp, tempMin, tempMax: Double
    let pressure, seaLevel, grndLevel, humidity: Int
    let tempKf: Double

    var rTemp: Int 
        return Int(temp)
    
    var rTempMax: Int 
        return Int(tempMax)
    
    var rTempMin: Int 
        return Int(tempMin)
    

    enum CodingKeys: String, CodingKey 
        case temp
        case tempMin = "temp_min"
        case tempMax = "temp_max"
        case pressure
        case seaLevel = "sea_level"
        case grndLevel = "grnd_level"
        case humidity
        case tempKf = "temp_kf"
    


【讨论】:

以上是关于为啥我不能访问这个数组 ForEach 循环中的数据? SwiftUI的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能使用 foreach 循环更新数组中的数据?

为啥在foreach循环中不能修改值类型实例

foreach语句遍历数组

为啥这个 foreach 循环缺少类中的属性?

为啥我的 forEach 循环没有编辑我的数组? [复制]

为啥我不能在“foreach”循环中取消设置变量?