Можно ли каждый раз создавать разное количество кнопок в SwiftUI? - PullRequest
0 голосов
/ 26 марта 2020

После нажатия кнопок мне нужно обновить sh вид с новым случайным количеством кнопок:

@State private var random = arc4random_uniform(5)
 ForEach(0..<random) {index in Button(Text("\(random)")){
  self.random = arc4random_uniform(5)     }

Обновляет заголовок кнопок, но их количество остается прежним

Ответы [ 3 ]

2 голосов
/ 26 марта 2020

Вот возможные решения (протестировано и работает с Xcode 11.4):

demo

struct TestRandomButtons: View {
    @State private var random = Array(repeating: 1, count: Int.random(in: 1...5))
    var body: some View {
        VStack {
            ForEach(random, id: \.self) {_ in
                Button("\(self.random.count)") { 
                    self.random = Array(repeating: 1, count: Int.random(in: 1...5)) 
                }
            }
        }
    }
}
0 голосов
/ 26 марта 2020

Это то же самое, что вы написали выше, но немного чище:

@State private var randomNumber = Int.random(in: 0..<5)

var body: some View {
    ForEach(0..<randomNumber, id: \.self) { _ in
        Button(action: {
            self.randomNumber = Int.random(in: 0..<5)
        }) {
            Text("\(self.randomNumber)")
        }
    }
}

При нажатии кнопки (или кнопок) в консоли выводится следующая ошибка:

ForEach<Range<Int>, Int, Button<Text>> count (2) != its initial count (1). ForEach (: content:) should only be used for *constant* data. Instead conform data to Идентифицируемый or use ForEach (: id: content:) and provide an explicit id !

Что это означает что для непостоянных (изменяющихся) данных при инициализации ForEach должен быть указан либо идентификатор, либо данные должны соответствовать опознаваемому. Таким образом, SwiftUI сможет отличать guish новые данные от старых.

Правильный код будет выглядеть так (также я изменил lowerBound на 1, так что всегда одна кнопка):

@State private var randomNumber = Int.random(in: 1..<5)

var body: some View {
    ForEach(0..<randomNumber, id: \.self) { _ in
        Button(action: {
            self.randomNumber = Int.random(in: 1..<5)
        }) {
            Text("\(self.randomNumber)")
        }
    }
}

Или, если вы хотите что-то более компактное:

@State private var random = Int.random(in: 1..<5)

var body: some View {
    ForEach(0..<random, id: \.self) { _ in
        Button("\(self.random)") {
            self.random = Int.random(in: 1..<5)
        }
    }
}
0 голосов
/ 26 марта 2020

Я бы предложил разделить вашу модель и вашу точку зрения. Это более быстрый способ SwiftUI сделать это.

class Model : ObservableObject {

      @Published var buttonLabels = ["Button: 1"]

      func generate() {
            let buttonCount = Int.random(in: 2...5)

            var newLabels = [String]()
            for index in 1...buttonCount {
                  newLabels.append("Button: \(index)")
            }
            buttonLabels = newLabels
      }
}

struct ContentView: View {

      @ObservedObject private var model = Model()

      var body: some View {

            return VStack() {
                  ForEach(model.buttonLabels, id: \.self) { label in
                        Button(action: { self.model.generate() }) { Text(label) }
                  }
            }
      }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...