Search code examples
swiftclassconstantsdeferredlet

Why did Xcode warn me about making this a constant, and why does it still change?


Within my updateBlob function, Xcode warned me that pos is unchanged and should be changed to a let constant, even though I can see that it's being changed, and running the program does indeed change the position values. This all seemed to happen when I updated the BlobPos class with a defer keyword to update the x/y coordinates when it is sent the radius value. Although I could avoid using defer, why does the compiler warn me of making pos a constant, and the program is still able to change what should presumably be a constant?

class BlobPos
{
    var x:CGFloat = 0
    var y:CGFloat = 0

    public init(radius:CGFloat) {

        defer {
            x = radius + 5
            y = radius + 5
        }
    }
}



class Blob
{
    
    var radius: CGFloat
    var pos: BlobPos
    
    init
    (
        radius: CGFloat,
        pos: BlobPos,
    )
    {
        self.radius = radius
        self.pos = pos
    }
    
}

func makeBlob() -> Blob
{
    
    let radius = 8
    
    let pos = BlobPos(radius:radius)
    
    return Blob(radius: radius, pos: pos)
}

func updateBlob(blob:Blob)
{

    let radius = blob.radius
    let pos    = blob.pos // compiler warning wanting me to turn this into a let constant instead of var

    pos.x += 6
    pos.y += 2
    
    blob.pos = pos // strangely, new position is set
    
}

Solution

  • That is because BlobPos is a class and changing a class's properties doesn't change its location in memory, which is how classes are passed around (by reference to their location in memory). If BlobPos were a structure, then you would have to declare it a variable because structures are passed around by their values (not references to their locations in memory).