Условно текст в SwiftUI в зависимости от значения массива - PullRequest
0 голосов
/ 29 сентября 2019

Я хочу сделать собственный стиль заполнителя, поэтому я пытаюсь использовать метод Mojtaba Hosseini в SwiftUI.Как изменить цвет заполнителя TextField?

if text.isEmpty {
            Text("Placeholder")
                .foregroundColor(.red)
        }

, но в моем случае я использую foreach с массивом для создания списка текстового поля и отображения или не для текста для имитации пользовательскогоplaceholder.

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

Как использовать динамический условный оператор с 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)")
        }
    }

}

Я могу запустить приложение, но у меня появляется эта ошибка в консоли, когда янажмите кнопку: ForEach, Int, ListeJoueurView> count (3)! = его начальный счет (2).ForEach(_:content:) следует использовать только для констант данных.Вместо этого приведите данные в соответствие Identifiable или используйте ForEach(_:id:content:) и предоставьте явное id!

Может кто-нибудь просветить меня?

1 Ответ

1 голос
/ 29 сентября 2019

TL; DR

Вам необходимо VStack, HStack, List и т. Д. Вне каждого ForEach.

Обновлено

Для второй части вашего вопроса вам нужно изменить свой ForEach, включив в него параметр id:

ForEach(self.ListeJoueurs[EquipName].indices, id: \.self)

Если данные не постоянны и число элементов может измениться, вам необходимо включитьid: \.self, поэтому SwiftUI знает, куда вставить новые представления.

Пример

Вот пример кода, демонстрирующий работающий вложенный 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)
            }
        }
    }
}

Объяснение

Вот что Документация Apple говорит о ForEach:

Структура, которая вычисляет представления по требованию из базовой коллекции [sic] идентифицированных данных.

Так что что-то вроде

ForEach(0..2, id: \.self) { number in
    Text(number.description)
}

действительно просто сокращение для

Text("0")
Text("1")
Text("2")

Таким образом, ваш ForEach создает несколько представлений, но этот синтаксис для объявления представлений действителен только внутри представлений, таких как VStack, HStack, List, Group и т. Д. Техническая причина заключается в том, что эти представления имеютинициализация, которая выглядит как

init(..., @ViewBuilder content: () -> Content)

и что @ViewBuilder совершает магию, которая допускает этот уникальный синтаксис.

...