Массив структур, не обновляемых в представлении - PullRequest
0 голосов
/ 08 января 2020

У меня есть массив наблюдаемых объектов, который содержит массив структур, которые содержат данные. Я хотел бы показать это на экране. Эти данные изначально отображаются на экране, но изменения не высовываются при внесении изменений в элемент массива. Я даже меняю свойство в структуре. Я попробовал это в моем классе менеджера также. Я немного покопался, несколько раз изменил свой подход, но я не могу заставить это работать. Я очень новичок в swiftui / swift и переполнении стека.

Полный код:

struct GameView: View {
    @State var value: CGFloat = 0
    @ObservedObject var circles = GameCircles()
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    var body: some View {
        ZStack {
            Color.primary
                .frame(width: 450, height: 800)
            self.circles.getViews()
                .onReceive(timer) { _ in
                    self.circles.tick()
            }
        }
        .edgesIgnoringSafeArea(.all)
        .gesture(DragGesture(minimumDistance: 20)
        .onChanged { gest in
            self.value = gest.location.x
        })
    }
}
class GameCircles: ObservableObject {
    @Published var circles: [GameCircle] = []

    func getViews() -> some View {
        ForEach(circles, id: \.id) { circle in
            circle.makeView()
        }
    }

    func tick() {
        for circle in circles {
            circle.tick()
            print(circle.y)
        }
        circles.append(GameCircle(x: Int.random(in: -200...200), y: -200))
    }

}

struct GameCircle: Identifiable {
    @State var x: Int
    @State var y: Int
    let color = Color.random()
    var id = UUID()

    func tick() {
        self.y += 1
    }

    func makeView() -> some View {
        return ZStack {
            Circle()
                .frame(width: 40, height: 40)
                .foregroundColor(color)
                .animation(.default)
            Text("\(Int(y))")
                .foregroundColor(.black)
        }
        .offset(x: CGFloat(self.x), y: CGFloat(self.y))
    }
}

1 Ответ

0 голосов

Я играл с этим кодом, пытаясь решить вашу проблему. И для меня было неожиданностью, что state var в View не изменилось в ForEach l oop (вы увидите это на скриншоте). Хорошо, я переписываю ваш код, теперь кружки идут вниз:

// MARK: models
class GameCircles: ObservableObject {

    @Published var circles: [CircleModel] = []

    func addNewCircle() {
        circles.append(CircleModel(x: CGFloat.random(in: -200...200), y: -200))
    }

}

struct CircleModel: Identifiable, Equatable {

    let id = UUID()
    var x: CGFloat
    var y: CGFloat

    mutating func pushDown() {
        self.y += 5
    }

}

// MARK: views
struct GameView: View {

    @State var gameSeconds = 0
    @ObservedObject var game = GameCircles()
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        ZStack {
            Color.primary
                .frame(width: 450, height: 800)

            ForEach(self.game.circles) { circle in
                CircleView(y: circle.y)
                    .offset(x: circle.x, y: circle.y)

                    .onReceive(self.timer) { _ in
                        let circleIndex = self.game.circles.firstIndex(of: circle)!
                        self.game.circles[circleIndex].pushDown()
                }
            }
            .onReceive(self.timer) { _ in
                self.game.addNewCircle()
            }
        }
        .edgesIgnoringSafeArea(.all)

    }

}

struct CircleView: View {

    @State var y: CGFloat

    var body: some View {
        ZStack {
            Circle()
                .frame(width: 40, height: 40)
                .foregroundColor(.red)
                .animation(.default)
            Text("\(Int(y))")
                .foregroundColor(.black)
        }

    }

}

struct GameView_Previews: PreviewProvider {
    static var previews: some View {
        GameView()
    }
}

enter image description here

, как вы видите, @State var y не меняется, и мне интересно Почему? Тем не менее, я надеюсь, что это может помочь вам.

PS Я переписал код несколько раз, так что это не единственное решение, и вы можете использовать tick() fun c как в вопросе и код будет понятнее

class GameCircles: ObservableObject {

    @Published var circles: [CircleModel] = []

    func tick() {

        for index in circles.indices {
            circles[index].pushDown()
        }

        circles.append(CircleModel(x: CGFloat.random(in: -200...200), y: -200))

    }

}

struct GameView: View {

    @State var gameSeconds = 0
    @ObservedObject var game = GameCircles()
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        ZStack {
            Color.primary
                .frame(width: 450, height: 800)

            ForEach(self.game.circles) { circle in
                CircleView(y: circle.y)
                    .offset(x: circle.x, y: circle.y)
            }
            .onReceive(self.timer) { _ in
                self.game.tick()
            }
        }
        .edgesIgnoringSafeArea(.all)

    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...