Как выполнить действие только один раз для каждого элемента в массиве (SwiftUI)? - PullRequest
1 голос
/ 07 августа 2020

У меня есть массив, содержащий 2 разных типа представления SwiftUI (скоро будет 6 разных типов), которые мне нужно повторить действие только один раз. Это разные типы игральных костей для настольных RPG (D4, D6, D20, et c), каждая из которых имеет функцию в структуре представлений для отображения случайного числа в текстовом поле. Проблема, с которой я сталкиваюсь, заключается в том, что у меня есть кнопка, которая должна запускать эти функции один раз для каждого представления, но вместо этого она устанавливает одно и то же число для всех представлений. Соответствующий код приведен ниже, обратите внимание, [...] где я сжал код, который не имеет отношения к делу. Спасибо!

Вот структура для D6DiceView, она содержит функцию для случайного броска (это полный текущий вид)

struct D6DiceView: View {

    @Binding var rolledValue: String
    
    var body: some View {
        VStack {
            ZStack {
                RoundedRectangle (cornerRadius: 10)
                    .frame(width: 100, height: 100)
                    .foregroundColor(.red)
                Text(rolledValue)
                    .font(.title)
                    .foregroundColor(.white)
            }
        }
    }

    func d6rollButtonPressed() {
        let randomInt = Int.random(in: 1..<7)
        rolledValue = "\(randomInt)"
        print("Random number is \(randomInt)")
    }
}

Это «основное» представление, где все кости будут удерживаться / Я только пытаюсь заставить D6DiceView работать, но после того, как это заработает, будет несколько разных видов кубиков.

Вот массив и начальное значение для каждого d ie

struct DiceSelectView: View {
    @State var viewArray = [] as [Any]
    @State var initialRolledValue = "1"
    ...
}

Здесь отображаются виды

LazyHGrid (rows: selectedDiceColumns)  {
    ForEach(0..<viewArray.count, id: \.self) { index in
        if self.viewArray[index] is D4DiceView {
            D4DiceView()
                .onTapGesture {
                    withAnimation(.spring()) {
                        self.viewArray.remove(at:index)
                        print("D4 tapped")
                    }
                }
        } else {
            D6DiceView(rolledValue: $initialRolledValue)
                .onTapGesture {
                    withAnimation(.spring()) {
                        self.viewArray.remove(at:index)
                        print("D6 tapped")
                    }
                }
        }
    }
}

Вот кнопка, которая нажимается для запуска броска кости

VStack {
    Button(action: rollButtonPressed, label: {
        Text("Roll Dice")
            .foregroundColor(.white)
            .padding()
            .frame(width: 120, height: 40)
            .background(Color(.systemIndigo))
            .cornerRadius(10)
    })
}

Вот функция что действия по нажатию кнопки, "прокатка" только D6DiceViews

func rollButtonPressed() {
    let d6Array = viewArray.compactMap {$0 as? D6DiceView}

    d6Array.forEach { item in
        item.d6rollButtonPressed()
    } 
}
...