简体   繁体   English

ForEach 在 SwiftUI 中无法按预期工作

[英]ForEach not working as expected in SwiftUI

In the current code when a text item is clicked the pageIndex gets updated but the UI doesn't react to the change在当前代码中,当单击文本项时,pageIndex 会更新,但 UI 不会对更改做出反应

ForEach(T2Array) { ele in
            Text(ele.name)
                .foregroundColor(ele.isSelected ? Color.blue : Color.black)
                .onTapGesture {
                    print(pageIndex)
                    pageIndex = 4
                    print(pageIndex)
                }
        }

The same code but when the ForEach syntax is used in a different way it works, why is its happening相同的代码但是当 ForEach 语法以不同的方式使用时,为什么会发生这种情况

ForEach(0...T2Array.count-1,id:\.self) { i in
                        Text(T2Array[i].name)
                            .foregroundColor(T2Array[i].isSelected ? Color.blue : Color.black)
                            .onTapGesture {
                                print(pageIndex)
                                pageIndex = 4
                                print(pageIndex)
                            }
                    }

Full code完整代码

import SwiftUI

struct T1Object:Identifiable{
    let id = UUID()
    var isSelected = false
    let name:String
}

struct T1:View{

    @State var T1Array:[T1Object] = [
        T1Object(isSelected: true, name: "Albin"),
        T1Object(isSelected: false, name: "Albin2"),
        T1Object(isSelected: false, name: "Albin3"),
        T1Object(isSelected: false, name: "Albin4"),
        T1Object(isSelected: false, name: "Albin5"),
        T1Object(isSelected: false, name: "Albin6"),
    ]

@State var pageIndex:Int = 0

  var body: some View {
    VStack{
        T2(T2Array: $T1Array,pageIndex:$pageIndex)
        Text("selected Index:\(pageIndex)")
        }
    }
}

struct T2:View{

    @Binding var T2Array:[T1Object]
    @Binding  var pageIndex:Int

var body: some View {
    
    TabView(selection: $pageIndex) {
        //This doesnt work
        ForEach(T2Array) { ele in
            Text(ele.name)
                .foregroundColor(ele.isSelected ? Color.blue : Color.black)
                .onTapGesture {
                    print(pageIndex)
                    pageIndex = 4
                    print(pageIndex)
                }
        }
        
        
        //..................
        //This commented code works fine why?
        //..................
        //            ForEach(0...T2Array.count-1,id:\.self) { i in
        //                Text(T2Array[i].name)
        //                    .foregroundColor(T2Array[i].isSelected ? Color.blue : Color.black)
        //                    .onTapGesture {
        //                        print(pageIndex)
        //                        pageIndex = 4
        //                        print(pageIndex)
        //                    }
        //            }
        
    }.tabViewStyle(PageTabViewStyle(indexDisplayMode:.never))
    .animation(Animation.easeInOut(duration: 0.5))
    .transition(.slide)
 }

}


struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        T1()
    }
}

Can anyone explain the difference between the two?谁能解释一下两者的区别?

Thnaks纳克斯

I think Paul Hudson explains it in this article: Creating tabs with TabView and tabItem() the gist of it is that the tabs are not an array of individual tabs, so to keep track of them you should use a tag() .我认为 Paul Hudson 在这篇文章中对此进行了解释: 使用 TabView 和 tabItem() 创建选项卡其要点是选项卡不是单个选项卡的数组,因此要跟踪它们,您应该使用tag() Why using the index range works, I am not sure.为什么使用索引范围有效,我不确定。 I suspect it is because you end up with an index that mimics your page index, but that is not the same thing.我怀疑这是因为您最终得到了一个模仿页面索引的索引,但这不是一回事。

If you do use a page, your first one works properly.如果您确实使用了一个页面,则您的第一个页面可以正常工作。 Of course, you need to use something unique to the array element, so I used it's UUID.当然,你需要使用数组元素特有的东西,所以我使用了它的UUID。

struct T1:View{
    
    @State var T1Array:[T1Object] = [
        T1Object(isSelected: true, name: "Albin"),
        T1Object(isSelected: false, name: "Albin2"),
        T1Object(isSelected: false, name: "Albin3"),
        T1Object(isSelected: false, name: "Albin4"),
        T1Object(isSelected: false, name: "Albin5"),
        T1Object(isSelected: false, name: "Albin6"),
    ]
    
    @State var pageIndex:UUID = UUID()
    
    init() { // the init() solely is here to set the pageIndex to the first element.
        pageIndex = T1Array.first!.id
    }
    
    var body: some View {
        VStack{
            T2(T2Array: $T1Array, pageIndex:$pageIndex)
            Text("selected Index:\(pageIndex)")
        }
    }
}


struct T2:View{
    
    @Binding var T2Array:[T1Object]
    @Binding  var pageIndex: UUID // make pageIndex a UUID (also in T1)
    
    var body: some View {
        
        TabView(selection: $pageIndex) {
            //This doesnt work
            ForEach(T2Array) { ele in
                Text(ele.name)
                    .tag(ele.id) // Set the .tag() here
                    .foregroundColor(ele.isSelected ? Color.blue : Color.black)
                    .onTapGesture {
                        print(pageIndex)
                        pageIndex = T2Array[3].id // This is the 4th element in T2Array
                        print(pageIndex)
                    }
            }
        }.tabViewStyle(PageTabViewStyle(indexDisplayMode:.never))
        .animation(Animation.easeInOut(duration: 0.5))
        .transition(.slide)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM