Home > Software engineering >  cannot use for...in or forEach loop in swift to print views in swift
cannot use for...in or forEach loop in swift to print views in swift

Time:12-09

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)
            }
        }
    }
}

CodePudding user response:

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.

Also, be careful when you post a Minimal, Reproducible Example. You should make a fresh app and make sure it compiles. In this case, you left out the WeatherButton() view, so it wasn't critical, but sometimes it is.

One more short note, generally you don't need to post your import in StackOverflow, and when you import SwiftUI you get Foundation imported by SwiftUI, so you don't need to import both.

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
        
    }
}
  • Related