Я играл с этим кодом, пытаясь решить вашу проблему. И для меня было неожиданностью, что 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()
}
}

, как вы видите, @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)
}
}