我将如何将类的每个实例设置为tabview的特定页面

发布于 2025-02-11 20:19:12 字数 3771 浏览 2 评论 0原文

我试图在应用程序视图中分配一个页面中的每个天气位置一个页面,但不确定如何实现这一目标。

我的位置视图中有一个CurrentPage变量,每次在屏幕上显示天气位置时应该添加1个,但是它只是在我拥有的整个foreach循环中添加一个,因此实际上并未将页码分配给天气视图。

我想知道是否有人知道如何在每个循环中迭代时将页码分配给每个位置。

我的位置视图如下所示。我尝试过的代码位于IF语句中的onAppear修饰符中的底部,但它不如上面说,我不确定这是否是执行此类操作的正确方法。任何帮助都很棒!

struct LocationView: View {
    @ObservedObject var weatherVM: WeatherViewViewModel
    @ObservedObject var multiLocationVM: MultiLocationViewModel
    
    @State private var pageSelection = 1
    @State var currentPage: Int = 0

    var body: some View {
        ZStack {
            LinearGradient(colors: [Color("BackgroundColorSun"), Color("BackgroundColorSky")], startPoint: .topLeading, endPoint: UnitPoint(x: 0.5, y: 0.5)).ignoresSafeArea()
        
            if multiLocationVM.weatherVM.count == 0 {
                BlankLocationView(multiLocationVM: multiLocationVM)
            } else {
                TabView(selection: $pageSelection) {
                    ForEach(multiLocationVM.weatherVM, id: \.self.city) { location in
                        VStack(spacing: 0) {
                            VStack(spacing: -10) {
                                ZStack(alignment: .center) {
                                    Text("\(location.getWeatherIconFor(icon: location.weatherIcon))")
                                        //.innerShadow(Color(.red))
                                        .font(.custom("SF Pro Text", size: 64))
                                        .innerShadow()
                                        //.foregroundColor(.gray)
                                        .offset(x: -70, y: -35)

                                    Text("\(location.getTempFor(temp: location.weather.current.temp))°")
                                        .font(.system(size: 96, weight: .semibold, design: .rounded))
                                        .tracking(-0.41)
                                        .shadow(color: .black.opacity(0.25), radius: 4, x: 0, y: 4)
                                }
                                .offset(x: 15)
                                Text(location.conditions)
                                    .font(.custom("SF Pro Display", size: 24))
                            }
                            .padding(EdgeInsets(top: -8, leading: 0, bottom: -8, trailing: 0))


                            VStack(spacing: -20) {
                                HourlyWeatherView(weatherVM: location)

                                DailyWeatherView(weatherVM: location)
                            }

                            Spacer()

                        }
                        .onAppear() {
                            if location.city != weatherVM.city {
                                weatherVM.city = location.city
                                currentPage += multiLocationVM.weatherVM.firstIndex(of: location)!
                                location.page = currentPage
                                
                                print("current \(currentPage)")
                                print("Location \(location.page)")
                            } else {
                                return
                            }
                        }
                        .tag(currentPage)
                    }
                }
                .tabViewStyle(.page(indexDisplayMode: .automatic))
                .indexViewStyle(.page(backgroundDisplayMode: .interactive))
            }
        }
        .padding(.bottom, 70)
        .ignoresSafeArea()
    }
}

struct LocationView_Previews: PreviewProvider {
    static var previews: some View {
        LocationView(weatherVM: WeatherViewViewModel(city: "Phoenix"), multiLocationVM: MultiLocationViewModel())
    }
}

I am trying to assign each weather location in my app a page in a tab view but am unsure on how to achieve this.

I have a currentPage variable in my location view which should add 1 every time a weather location is shown on screen but instead it just keeps adding one throughout the entire foreach loop I have, so a page number isn't actually assigned to a weather view.

I was wondering if anyone knew how I could assign a page number to each location when iterating through my for each loop.

My location view is shown below. The code I tried is at the bottom in the onAppear modifier in the if statement but it doesn't work like I said above and I am not sure if this is even the right approach for doing something like this. Any help would be great!

struct LocationView: View {
    @ObservedObject var weatherVM: WeatherViewViewModel
    @ObservedObject var multiLocationVM: MultiLocationViewModel
    
    @State private var pageSelection = 1
    @State var currentPage: Int = 0

    var body: some View {
        ZStack {
            LinearGradient(colors: [Color("BackgroundColorSun"), Color("BackgroundColorSky")], startPoint: .topLeading, endPoint: UnitPoint(x: 0.5, y: 0.5)).ignoresSafeArea()
        
            if multiLocationVM.weatherVM.count == 0 {
                BlankLocationView(multiLocationVM: multiLocationVM)
            } else {
                TabView(selection: $pageSelection) {
                    ForEach(multiLocationVM.weatherVM, id: \.self.city) { location in
                        VStack(spacing: 0) {
                            VStack(spacing: -10) {
                                ZStack(alignment: .center) {
                                    Text("\(location.getWeatherIconFor(icon: location.weatherIcon))")
                                        //.innerShadow(Color(.red))
                                        .font(.custom("SF Pro Text", size: 64))
                                        .innerShadow()
                                        //.foregroundColor(.gray)
                                        .offset(x: -70, y: -35)

                                    Text("\(location.getTempFor(temp: location.weather.current.temp))°")
                                        .font(.system(size: 96, weight: .semibold, design: .rounded))
                                        .tracking(-0.41)
                                        .shadow(color: .black.opacity(0.25), radius: 4, x: 0, y: 4)
                                }
                                .offset(x: 15)
                                Text(location.conditions)
                                    .font(.custom("SF Pro Display", size: 24))
                            }
                            .padding(EdgeInsets(top: -8, leading: 0, bottom: -8, trailing: 0))


                            VStack(spacing: -20) {
                                HourlyWeatherView(weatherVM: location)

                                DailyWeatherView(weatherVM: location)
                            }

                            Spacer()

                        }
                        .onAppear() {
                            if location.city != weatherVM.city {
                                weatherVM.city = location.city
                                currentPage += multiLocationVM.weatherVM.firstIndex(of: location)!
                                location.page = currentPage
                                
                                print("current \(currentPage)")
                                print("Location \(location.page)")
                            } else {
                                return
                            }
                        }
                        .tag(currentPage)
                    }
                }
                .tabViewStyle(.page(indexDisplayMode: .automatic))
                .indexViewStyle(.page(backgroundDisplayMode: .interactive))
            }
        }
        .padding(.bottom, 70)
        .ignoresSafeArea()
    }
}

struct LocationView_Previews: PreviewProvider {
    static var previews: some View {
        LocationView(weatherVM: WeatherViewViewModel(city: "Phoenix"), multiLocationVM: MultiLocationViewModel())
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

丢了幸福的猪 2025-02-18 20:19:12

恕我直言,您不需要CurrentPage Counter作为tabview(selection:)为您处理。选择,在您的情况下,pageSelection将在用户刷新时进行更新,或者您可以通过编程方式设置它。您只需要提供拟合.tag

//  dummy test data
struct Weather {
    var city: String
    var icon: String
    var temp: Int
    var condition: String
}

let multiLocationVM = [
    Weather(city: "Vancouver", icon: "cloud", temp: 64, condition: " Mostly Cloudy"),
    Weather(city: "New York", icon: "cloud.sun", temp: 78, condition: " Mostly Sunny"),
    Weather(city: "Los Angeles", icon: "sun.max", temp: 91, condition: " Sunny"),
]

struct ContentView: View {
    
    @State private var pageSelection = "Vancouver" // default here
    @State var currentPage: Int = 0
    
    var body: some View {
        ZStack {
            LinearGradient(colors: [Color(.yellow), Color(.blue)], startPoint: .topLeading, endPoint: UnitPoint(x: 0.5, y: 0.5)).ignoresSafeArea()
            
            if multiLocationVM.count == 0 {
                // BlankLocationView(multiLocationVM: multiLocationVM)
            } else {
                TabView(selection: $pageSelection) {
                    ForEach(multiLocationVM, id: \.city) { location in
                        LocalWeather(location: location)
                            .tag(location.city) // set tab id here
                    }
                }
                .tabViewStyle(.page(indexDisplayMode: .automatic))
            }
        }
        .padding(.bottom, 70)
        .ignoresSafeArea()
    }
}


struct LocalWeather: View {
    
    let location: Weather
    
    var body: some View {
        VStack(alignment: .center, spacing: 0) {
            VStack(alignment: .center, spacing: -10) {
                ZStack(alignment: .center) {
                    Image(systemName: location.icon)
                        .font(.custom("SF Pro Text", size: 32))
                        .offset(x: -90, y: -35)
                    
                    Text("\(location.temp)")
                        .font(.system(size: 96, weight: .semibold, design: .rounded))
                        .tracking(-0.41)
                        .shadow(color: .black.opacity(0.25), radius: 4, x: 0, y: 4)
                }
                .offset(x: 15)
                Text(location.condition)
                    .font(.custom("SF Pro Display", size: 24))
            }
            .padding(EdgeInsets(top: -8, leading: 0, bottom: -8, trailing: 0))
            
            Spacer()
        }
    }
}

”在此处输入图像说明”

IMHO you don't need the currentPage counter as TabView(selection: )is handling that for you. The selection, in your case pageSelection will update when the user swipes, or you can set it programmatically. You just have to provide a fitting .tag:

//  dummy test data
struct Weather {
    var city: String
    var icon: String
    var temp: Int
    var condition: String
}

let multiLocationVM = [
    Weather(city: "Vancouver", icon: "cloud", temp: 64, condition: " Mostly Cloudy"),
    Weather(city: "New York", icon: "cloud.sun", temp: 78, condition: " Mostly Sunny"),
    Weather(city: "Los Angeles", icon: "sun.max", temp: 91, condition: " Sunny"),
]

struct ContentView: View {
    
    @State private var pageSelection = "Vancouver" // default here
    @State var currentPage: Int = 0
    
    var body: some View {
        ZStack {
            LinearGradient(colors: [Color(.yellow), Color(.blue)], startPoint: .topLeading, endPoint: UnitPoint(x: 0.5, y: 0.5)).ignoresSafeArea()
            
            if multiLocationVM.count == 0 {
                // BlankLocationView(multiLocationVM: multiLocationVM)
            } else {
                TabView(selection: $pageSelection) {
                    ForEach(multiLocationVM, id: \.city) { location in
                        LocalWeather(location: location)
                            .tag(location.city) // set tab id here
                    }
                }
                .tabViewStyle(.page(indexDisplayMode: .automatic))
            }
        }
        .padding(.bottom, 70)
        .ignoresSafeArea()
    }
}


struct LocalWeather: View {
    
    let location: Weather
    
    var body: some View {
        VStack(alignment: .center, spacing: 0) {
            VStack(alignment: .center, spacing: -10) {
                ZStack(alignment: .center) {
                    Image(systemName: location.icon)
                        .font(.custom("SF Pro Text", size: 32))
                        .offset(x: -90, y: -35)
                    
                    Text("\(location.temp)")
                        .font(.system(size: 96, weight: .semibold, design: .rounded))
                        .tracking(-0.41)
                        .shadow(color: .black.opacity(0.25), radius: 4, x: 0, y: 4)
                }
                .offset(x: 15)
                Text(location.condition)
                    .font(.custom("SF Pro Display", size: 24))
            }
            .padding(EdgeInsets(top: -8, leading: 0, bottom: -8, trailing: 0))
            
            Spacer()
        }
    }
}

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文