Izac Mac
Izac Mac

Reputation: 502

cannot use for...in or forEach loop in swift to print views in swift

so here is the problem. my code runs fine when i give values within the file. However, i made a separate model file from which i want to iterate through an Array of WeatherDay objects to print them to make them dynamic. However, logically it sounds easy but i run into these annoying error which wont let me compile. anyone help!! Code given below :

struct ContentView: View {
    
    @State private var isNight = false
    
    var body: some View {
        ZStack {
            var selectedWeather = getWeatherValues()
            // binding basically enforces that the value for the object stays the same
            BackgroundView(isNight: $isNight)
            
            VStack {
                let days = selectedWeather.getWeatherDayListData()
                CityTextView(cityName: selectedWeather.getCity())
                
//                first object
                mainWeatherView(isNight: $isNight, todayWeather:
                                    selectedWeather.getWeatherDayListData()[0])

                HStack(spacing: 20) {
                    weatherDayView(weatherDays: selectedWeather.getWeatherDayListData())

                }
                
                
            }
            Spacer() //basically used to move the text to the top of the frame
            Button {
                isNight.toggle()
            } label: {
                WeatherButton(title: "Change Day Time",
                              textColor: .blue,
                              backgroundColor: .white)
                
            }
            Spacer()
        }
    }
}

struct weatherDayView: View {
    //this is where i get all the errors like
    //closure expression is unused
    //expected { in struct
    //expressions are not allowed at the top level.
    
    @State var weatherDays: [WeatherDay]
    
    var body: some View {
        ForEach(weatherDays, id: \.self) { singleDay in
            
            VStack {
                Text(singleDay.dayOfWeek)
                    .font(.system(size: 18, weight: .medium, design: .default))
                    .foregroundColor(.white)
                Image(systemName: singleDay.ImageName)
                    .renderingMode(.original)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 40, height: 40)
                Text("\(singleDay.temperature)°")
                    .font(.system(size: 28, weight: .medium))
                    .foregroundColor(.white)
            }
        }
    }
}

Upvotes: 0

Views: 1006

Answers (1)

Yrb
Yrb

Reputation: 9665

There were a bunch of errors in here, starting with your ForEach. ForEach is not a for...in, though they have a similar purpose: looping through a random access collection. ``for...inis used outside of a view, andForEach` is used in a view, and creates a view per element.

Next, you can't declare a struct like a function. The parameters go inside the struct declaration. After that it was a case of working up the view hierarchy making sure everything had the correct Type. I have fixed your code, so you have an example, though you can definitely tighten your code a great deal. I would highly recommend going through Apple's SwiftUI Tutorials and Stanford's CS193P course as these are basic SwiftUI issues.

struct ContentView: View {
    @State private var isNight = false
    
    var body: some View {
        ZStack {
            // binding basically enforces that the value for the object stays the same
            BackgroundView(isNight: $isNight)
            VStack {
                let selectedWeather = getWeatherValues()
                
                CityTextView(cityName: selectedWeather.getCity())
                mainWeatherView(isNight: $isNight, temperature: 76)
                
                HStack(spacing: 20) {
                    weatherDayView(weatherDays: selectedWeather.getWeatherDayListData())
                }
                
                
                
            }
            Spacer() //basically used to move the text to the top of the frame
            Button {
                isNight.toggle()
            } label: {
                WeatherButton(title: "Change Day Time",
                              textColor: .blue,
                              backgroundColor: .white)
                
            }
            Spacer()
        }
        
    }
}


struct weatherDayView: View {
//this is where i get all the errors like
//closure expression is unused
//expected { in struct
//expressions are not allowed at the top level.
        
    @State var weatherDays: [WeatherDay]
    
        var body: some View {
            ForEach(weatherDays, id: \.self) { singleDay in

            VStack {
                Text(singleDay.dayOfWeek)
                    .font(.system(size: 18, weight: .medium, design: .default))
                    .foregroundColor(.white)
                Image(systemName: singleDay.ImageName)
                    .renderingMode(.original)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 40, height: 40)
                Text("\(singleDay.temperature)°")
                    .font(.system(size: 28, weight: .medium))
                    .foregroundColor(.white)
            }
        }
    }
}

edit:

Added WeatherDay conforming to Hashable.

struct WeatherDay: Hashable {
    var dayOfWeek: String
    var ImageName: String
    var temperature: Int
    
    init(dayOfWeek: String, ImageName: String, temperature: Int)
    {
        self.dayOfWeek = dayOfWeek
        self.ImageName = ImageName
        self.temperature = temperature
        
    }
}

Upvotes: 1

Related Questions