How do I use "views" and structures / what's wrong with my code?

what's wrong with my code? im getting error "Closure containing control flow statement cannot be used with result builder 'ViewBuilder' " next to my for loop...


//
//  ContentView.swift
//  Bouncing Balls Simulation without ChatGPT's Code
//
//  Created by Hillary Basile on 3/30/25.
//

import SwiftUI
import Foundation
import CoreGraphics


class Balls
{
    //var color: String
    var xPosition: Int
    var yPosition: Int
    var xVelocity: Int
    var yVelocity: Int
    var radius: Int
    var gravity: CGFloat
    var restitution: Int
    
    var other: Balls?
    
    init(xPosition: Int, yPosition: Int, xVelocity: Int, yVelocity: Int, radius: Int, gravity: CGFloat, restitution: Int)
    //ADD COLOR
    {
        //self.color = color
        self.xPosition = xPosition
        self.yPosition = yPosition
        self.xVelocity = xVelocity
        self.yVelocity = yVelocity
        self.radius = radius
        self.gravity = gravity
        self.restitution = restitution
    }
    
    let ball1: Balls = Balls (xPosition: 100, yPosition: 100, xVelocity: 3, yVelocity: 0, radius: 3, gravity: 0.3, restitution: 1)
    let ball2: Balls = Balls (xPosition: 200, yPosition: 50, xVelocity: -2, yVelocity: 2, radius: 3, gravity: 0.3, restitution: 1)
    let ball3: Balls = Balls  (xPosition: 300, yPosition: 150, xVelocity: 4, yVelocity: -3, radius: 3, gravity: 0.3, restitution: 1)
    
    struct UserView: View
    {
        
        var timer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect()
        
        
        var body: some View
        {
            VStack
            {
                //Background color
                Color.gray.edgesIgnoringSafeArea(.all)
                
                //var balls [Int] = [ball1; ball2; ball3]
                    for item in Balls
                    {
                        Circle()
                            .fill(Color.black)
                            .frame(width: 50, height: 50)
                            .position(Balls[].xPosition, Balls[].yPosition)
                        
                        
                            .onReceive(timer)
                        {
                            self.yVelocity += self.gravity
                            self.xPosition = CGPoint(self.xPosition + self.xVelocity)
                            self .yPosition = CGPoint (self.yPosition + self.yVelocity)
                            
                            if self.yPosition >= 500 - 25
                            {
                                self.yPosition = 500 - 25
                                self.yVelocity = -self.yVelocity * self.restitution
                            }
                            
                            if self.xPosition <= 25
                            {
                                self.xPosition = 25
                                self.xVelocity = -self.xVelocity
                            }
                            
                            if self.xPosition >= 375
                            {
                                self.xPosition = 375
                                self  .xVelocity = -self.velocityX
                            }
                            
                            
                            let dx: int = other.xPosition - self.xPosition
                            let dy: int = other.yPosition - self.yPosition
                            let distance: int = sqrt (dx * dx + dy * dy)
                            if distance < self.radius + other.radius
                            {
                                self.xVelocity = -self.xVelocity * self.restitution
                                self.yVelocity = -self.yVelocity * self.restitution
                                other.xVelocity = -other.xVelocity * self.restitution
                                other.yVelocity = -other.yVelocity * self.restitution
                            }
                        }
         
                        }
                    }
                }
            }
        }
    }
    
    
    #Preview
    {
        ContentView()
    }
}

There are so many things wrong with your code:

  1. You've created a class Balls, which should contain some variables and methods, but you've added a struct UserView inside. This struct should be outside of the class, at the same level as the class.
  2. Your #Preview should be at the root level, just like the class and the struct.
  3. for item in Balls is completely wrong for two reasons. Firstly, you're trying to access the class Balls not an instance of it, and secondly inside a View you have to use forEach, i.e. balls.forEach { item in.
  4. On line 57 you commented out //var balls [Int] = [ball1; ball2; ball3]. This syntax is wrong. You're missing a colon before the [Int] and you have to use commas not semicolons to separate items in an array, i.e. //var balls: [Int] = [ball1, ball2, ball3]. But, even then this is wrong because you're trying to create an array of Ints but you're passing in three objects which are of the type Balls.

I think you need to go back to the beginning and look at how to write Swift and SwiftUI code. There are so many issues in your code here.

I note, right at the top, on line 4, you've got a comment: Bouncing Balls Simulation without ChatGPT's Code. I fear you've attempted to use ChatGPT to write code for you. Please stop doing this. Learn how to write code properly. ChatGPT won't help you, and it has clearly led you down the wrong path.

There are loads of resources to learn Swift. Apple provides tons of sample code that you can read, follow along with, and learn without resorting to unproven, dodgy 'AI'.

what's wrong with my code?

Sorry to say, nearly everything.

There are so many errors everywhere. You should start studying Swift first. As DarkPaw said, AI (ChatGPT or other) does not replace plain intelligence. It seems you don't even understand your own code, isn't it ?

There are even many typos in code:

  • extra }
  • Balls[].xPosition is wrong syntax. What do you mean here ?

The problem for the error message (there are likely many other) is you call

for item in Balls

You have to use ForEach in a view.

In addition, Balls is not an array, even less an instance of array.

And View struct should be outside of the class. Otherwise, how do you plan to access it ?

Here is a start to correct those many errors:

class Balls: Identifiable {
    //var color: String
    var xPosition: Int
    var yPosition: Int
    var xVelocity: Int
    var yVelocity: Int
    var radius: Int
    var gravity: CGFloat
    var restitution: Int
    
    var other: Balls?
    
    init(xPosition: Int, yPosition: Int, xVelocity: Int, yVelocity: Int, radius: Int, gravity: CGFloat, restitution: Int)
    //ADD COLOR
    {
        //self.color = color
        self.xPosition = xPosition
        self.yPosition = yPosition
        self.xVelocity = xVelocity
        self.yVelocity = yVelocity
        self.radius = radius
        self.gravity = gravity
        self.restitution = restitution
    }
}

struct UserView: View {
    
    let ball1: Balls = Balls (xPosition: 100, yPosition: 100, xVelocity: 3, yVelocity: 0, radius: 3, gravity: 0.3, restitution: 1)
    let ball2: Balls = Balls (xPosition: 200, yPosition: 50, xVelocity: -2, yVelocity: 2, radius: 3, gravity: 0.3, restitution: 1)
    let ball3: Balls = Balls  (xPosition: 300, yPosition: 150, xVelocity: 4, yVelocity: -3, radius: 3, gravity: 0.3, restitution: 1)
    
    var timer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect()
    @State var balls: [Balls]
    
    init() {
        balls = [ball1, ball2, ball3]
    }
    
    var body: some View {
        VStack {
            //Background color
            Color.gray.edgesIgnoringSafeArea(.all)
            
            //var balls [Int] = [ball1; ball2; ball3]
            //                for item in Balls {
            ForEach($balls) { $ball in      // You change ball later, so a binding here
                Circle()
                    .fill(Color.black)
                    .frame(width: 50, height: 50)
                    .position(x: CGFloat($ball.xPosition.wrappedValue), y: CGFloat($ball.yPosition.wrappedValue)) // Wrappedvalue because ball is a binding
                
                    .onReceive(timer) { _ in    // Need on argument in the closure
                        // self.yVelocity += self.gravity  // self refers to View, not to a ball
                        ball.yVelocity = ball.yVelocity + Int(ball.gravity)  // One is Int, the other Float. Why ? That forbids +=
                        // ball.xPosition = CGPoint(ball.xPosition + ball.xVelocity) // That's not a CGPoint, needs 2 arguments
                        ball.xPosition = ball.xPosition + ball.xVelocity
                        ball .yPosition = ball.yPosition + ball.yVelocity
                        
                        if ball.yPosition >= 500 - 25 {
                            ball.yPosition = 500 - 25
                            ball.yVelocity = -ball.yVelocity * ball.restitution
                        }
                        
                        if ball.xPosition <= 25 {
                            ball.xPosition = 25
                            ball.xVelocity = -ball.xVelocity
                        }
                        
                        if ball.xPosition >= 375 {
                            ball.xPosition = 375
                            ball.xVelocity = -ball.xVelocity // I suppose that's what you mean insted of ball.velocityX
                        }
                        
                        /* errrors below you'll have to correct yourself
                         let dx: int = other.xPosition - self.xPosition
                         let dy: int = other.yPosition - self.yPosition
                         let distance: int = sqrt (dx * dx + dy * dy)
                         if distance < self.radius + other.radius {
                         self.xVelocity = -self.xVelocity * self.restitution
                         self.yVelocity = -self.yVelocity * self.restitution
                         other.xVelocity = -other.xVelocity * self.restitution
                         other.yVelocity = -other.yVelocity * self.restitution
                         }
                         */
                    }
                
            }
        }
    }
}

here is a version of my code without any of that structure/view/body parts of the language that I don't understand

maybe this will be easier to fix because its basically just the logic of the program that I want to write...sort of modeled after my knowledge of C++, and im trying to get to a version that is the correct swift syntax, etc.

like I said in the comments, im really looking for help with structures - bodies, views, @state, @observedobject, etc

class Balls
{
    //var color: String
    var xPosition: Int
    var yPosition: Int
    var xVelocity: Int
    var yVelocity: Int
    var radius: Int
    var gravity: CGFloat
    var restitution: Int

    var other: Balls?
    
    init(xPosition: Int, yPosition: Int, xVelocity: Int, yVelocity: Int, radius: Int, gravity: CGFloat, restitution: Int)
    //ADD COLOR
    {
        //self.color = color
        self.xPosition = xPosition
        self.yPosition = yPosition
        self.xVelocity = xVelocity
        self.yVelocity = yVelocity
        self.radius = radius
        self.gravity = gravity
        self.restitution = restitution
    }
    
    let ball1: Balls = Balls (xPosition: 100, yPosition: 100, xVelocity: 3, yVelocity: 0, radius: 3, gravity: 0.3, restitution: 1)

    let ball2: Balls = Balls (xPosition: 200, yPosition: 50, xVelocity: -2, yVelocity: 2, radius: 3, gravity: 0.3, restitution: 1)

    let ball3: Balls = Balls  (xPosition: 300, yPosition: 150, xVelocity: 4, yVelocity: -3, radius: 3, gravity: 0.3, restitution: 1)

        
        var timer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect()
        
        //Background color
        Color.gray.edgesIgnoringSafeArea(.all)
                
                
                
                 for item in Balls
                    {
                        Circle()
                            .fill(Color.black)
                            .frame(width: 50, height: 50)
                            .position(Balls[].xPosition, Balls[].yPosition)
                        
                        
                            .onReceive(timer)
                        {
                            self.yVelocity += self.gravity
                            self.xPosition = CGPoint(self.xPosition + self.xVelocity)
                            self .yPosition = CGPoint (self.yPosition + self.yVelocity)
                            
                            if self.yPosition >= 500 - 25
                            {
                                self.yPosition = 500 - 25
                                self.yVelocity = -self.yVelocity * self.restitution
                            }
                            
                            if self.xPosition <= 25
                            {
                                self.xPosition = 25
                                self.xVelocity = -self.xVelocity
                            }
                            
                            if self.xPosition >= 375
                            {
                                self.xPosition = 375
                                self  .xVelocity = -self.velocityX
                            }
                            
                            
                            let dx: int = other.xPosition - self.xPosition
                            let dy: int = other.yPosition - self.yPosition
                            let distance: int = sqrt (dx * dx + dy * dy)
                            if distance < self.radius + other.radius
                            {
                                self.xVelocity = -self.xVelocity * self.restitution
                                self.yVelocity = -self.yVelocity * self.restitution
                                other.xVelocity = -other.xVelocity * self.restitution
                                other.yVelocity = -other.yVelocity * self.restitution
                            }
                        }
                    }
            

We've already explained.

A class contains variables and methods that act on those variables. For example, you might have a Ball class that contains x and y CGFloats for the position, and you'll have methods in the class that add/remove 1 to the values to move the ball's position, e.g.:

class Ball {
	var x: CGFloat
	var y: CGFloat

	init(x: CGFloat, y: CGFloat) {
		self.x = x
		self.y = y
	}

	func moveRight() {
		x += 1
	}

	func moveLeft() {
		x -= 1
	}

	func moveUp() {
		y -= 1
	}

	func moveDown() {
		y += 1
	}
}

That's the class, all done.

And to use it, you'd do this:

let ball: Ball = Ball(x: 20, y: 50)
redBall.moveDown()  // redBall.y is now 51
redBall.moveLeft()  // redBall.x is now 19

You've just posted code where lines 27, 29 and 31 create three instances of your Balls class inside the Balls class. That's not how it works. You should create those three instances of Balls outside of the class where you're going to use them.

Then, despite @Claude31 giving you actual working code showing you where the 'struct Userview: View goes, you've ignored it completely, and put your UI code inside your Balls class.

Then, you have a go at us for actually helping you and suggesting you don't use AI to learn coding.

We are trying to help you, but if you don't take onboard any of our suggestions, why should we bother? I certainly aren't going to bother anymore.

I am not sure how to declare "other"

cannot find "other" in scope

this is the last error message in my code, I fixed the other errors. if you have a different way of referencing the random balls that will collide with the current ball, that's helpful too

How do I use "views" and structures / what's wrong with my code?
 
 
Q