SwiftUI 中的有条件文本取决于数组值

Nic*_*s M 2 text if-statement view conditional-statements swiftui

我想制作占位符自定义样式,所以我尝试在SwiftUI 中使用 Mojtaba Hosseini 的方法。如何更改 TextField 的占位符颜色?

if text.isEmpty {
            Text("Placeholder")
                .foregroundColor(.red)
        }
Run Code Online (Sandbox Code Playgroud)

但就我而言,我使用带有 Array 的 foreach 来制作 Textfield 和 Display 列表,或者不是用于模拟自定义占位符的 Text。

          ForEach(self.ListeEquip.indices, id: \.self) { item in
     ForEach(self.ListeJoueurs[item].indices, id: \.self){idx in
// if self.ListeJoueurs[O][O] work
        if self.ListeJoueurs[item][index].isEmpty {
                                    Text("Placeholder")
                                        .foregroundColor(.red)
                                }
    }
    }
Run Code Online (Sandbox Code Playgroud)

如何在 foreach 中使用动态条件?


现在我有另一个问题:

我有这个代码:

struct EquipView: View {
    @State var ListeJoueurs = [
        ["saoul", "Remi"],
        ["Paul", "Kevin"]
    ]
    @State var ListeEquip:[String] = [
        "Rocket", "sayans"
    ]

    var body: some View {
        VStack { // Added this
            ForEach(self.ListeEquip.indices) { item in

                BulleEquip(EquipName: item, ListeJoueurs: self.$ListeJoueurs, ListeEquip: self.$ListeEquip)

            }
        }
    }

}


struct BulleEquip: View {
    var EquipName = 0
    @Binding var ListeJoueurs :[[String]]
    @Binding var ListeEquip :[String]

    var body: some View {
        VStack{
        VStack{
            Text("Équipe \(EquipName+1)")
        }
        VStack { // Added this
            ForEach(self.ListeJoueurs[EquipName].indices) { index in
                ListeJoueurView(EquipNamed: self.EquipName, JoueurIndex: index, ListeJoueurs: self.$ListeJoueurs, ListeEquip: self.$ListeEquip)
            }
            HStack{
            Button(action: {
                self.ListeJoueurs[self.EquipName].append("")  //problem here
            }){
                Text("button")
                }
            }
        }
    }
    }

}

struct ListeJoueurView: View {
    var EquipNamed = 0
    var JoueurIndex = 0
    @Binding var ListeJoueurs :[[String]]
    @Binding var ListeEquip :[String]

    var body: some View {
        HStack{
            Text("Joueur \(JoueurIndex+1)")
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

我可以运行应用程序,但是当我单击按钮时,控制台中出现此错误:ForEach, Int, ListeJoueurView> count (3) != its initial count (2)。ForEach(_:content:)应该只用于常量数据。而是使数据符合Identifiable或使用ForEach(_:id:content:)并提供明确的id!

有人可以启发我吗?

Joh*_* M. 5

TL; 博士

你需要一个VStackHStackList外各等ForEach

更新

对于问题的第二部分,您需要更改 ForEach 以包含 id 参数:

ForEach(self.ListeJoueurs[EquipName].indices, id: \.self)
Run Code Online (Sandbox Code Playgroud)

如果数据不是恒定的并且元素的数量可能会发生变化,您需要包含id: \.selfSwiftUI 知道在哪里插入新视图。

例子

下面是一些演示工作嵌套 ForEach 的示例代码。我创建了一个与您尝试调用它的方式相匹配的数据模型。

struct ContentView: View {

    // You can ignore these, since you have your own data model
    var ListeEquip: [Int] = Array(1...3)
    var ListeJoueurs: [[String]] = []
    // Just some random data strings, some of which are empty
    init() {
        ListeJoueurs = (1...4).map { _ in (1...4).map { _ in Bool.random() ? "Text" : "" } }
    }

    var body: some View {
        VStack { // Added this
            ForEach(self.ListeEquip.indices, id: \.self) { item in
                VStack { // Added this
                    ForEach(self.ListeJoueurs[item].indices, id: \.self) { index in
                        if self.ListeJoueurs[item][index].isEmpty { // If string is blank
                            Text("Placeholder")
                                .foregroundColor(.red)
                        } else { // If string is not blank
                            Text(self.ListeJoueurs[item][index])
                        }
                    }
                }.border(Color.black)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

解释

以下是Apple 的文档中关于 ForEach 的说明:

一种根据[原文如此]识别数据的基础集合按需计算视图的结构。

所以像

ForEach(0..2, id: \.self) { number in
    Text(number.description)
}
Run Code Online (Sandbox Code Playgroud)

真的只是简写

Text("0")
Text("1")
Text("2")
Run Code Online (Sandbox Code Playgroud)

所以你的 ForEach 正在制作一堆视图,但是这种声明视图的语法只在 VStack、HStack、List、Group 等视图内有效。技术原因是因为这些视图有一个看起来像

init(..., @ViewBuilder content: () -> Content)
Run Code Online (Sandbox Code Playgroud)

@ViewBuilder做了一些允许这种独特语法的魔法。