使用 ForEach 在 SwiftUI 中选择时,有没有办法更改 tabItem 的图像?

Is there a way to change a tabItem's image when selected in SwiftUI when using ForEach?

考虑 SwiftUI 中最简单的选项卡视图应用程序:

struct ContentView: View {
    @State private var selection = 0
 
    var body: some View {
        TabView(selection: $selection){
            Text("First View")
                .font(.title)
                .tabItem {
                    VStack {
                        Image("first")
                        Text("First")
                    }
                }
                .tag(0)
            Text("Second View")
                .font(.title)
                .tabItem {
                    VStack {
                        Image("second")
                        Text("Second")
                    }
                }
                .tag(1)
        }
    }
}

只要点击一个选项卡,就会重新加载选项卡项目,如果需要,您可以通过将选择与标签进行比较来更改所选选项卡的图像。但是,如果您在变量中有动态数量的选项卡并使用 ForEach 来显示它们,那将不起作用:

struct ContentView: View {
    @State private var selection = 0

    private var items: [AnyView] {
        return [
            AnyView(Text("First View")
                .font(.title)
                .tabItem {
                        VStack {
                            Image("first1")
                            Text("First1")
                        }
                }
                .tag(0)),
            AnyView(Text("Second View")
                .font(.title)
                .tabItem {
                    VStack {
                        Image("second")
                        Text("Second")
                    }
                }
                .tag(1))
        ]
    }
 
    var body: some View {
        TabView(selection: $selection){
            ForEach(0..<self.items.count) { index in
                self.items[index]
            }
        }
    }
}

ForEach 的主体在视图重新加载时不会被调用。有没有办法在您的 TabView 中使用 ForEach 来完成更改图像?

尝试以下操作:

struct ContentView: View {
    @State private var selection = 0
 
    var body: some View {
        TabView(selection: $selection){
            Text("First View")
                .font(.title)
                .tabItem {
                    VStack {
                        Image(systemName: selection == 0 ? "xmark" : "plus")
                        Text("First")
                    }
                }
                .tag(0)
            Text("Second View")
                .font(.title)
                .tabItem {
                    VStack {
                        Image(systemName: selection == 1 ? "xmark" : "minus")
                        Text("Second")
                    }
                }
                .tag(1)
        }
    }
}

答案在文档中!使用具有范围的 ForEach 时:

    /// Creates an instance that computes views on demand over a *constant*
    /// range.
    ///
    /// This instance only reads the initial value of `data` and so it does not
    /// need to identify views across updates.
    ///
    /// To compute views on demand over a dynamic range use
    /// `ForEach(_:id:content:)`.

因此,要实现此功能,请使用 ForEach(_:id:content:)