"Expression is not assignable" -- Problem assigning float as sum of two other floats in Xcode?

36,311

Solution 1

The other answers don't exactly explain what's going on here, so this is the basic problem:

When you write blackKey.center.x, the blackKey.center and center.x both look like struct member accesses, but they're actually completely different things. blackKey.center is a property access, which desugars to something like [blackKey center], which in turn desugars to something like objc_msgSend(blackKey, @selector(center)). You can't modify the return value of a function, like objc_msgSend(blackKey, @selector(center)).x = 2 — it just isn't meaningful, because the return value isn't stored anywhere meaningful.

So if you want to modify the struct, you have to store the return value of the property in a variable, modify the variable, and then set the property to the new value.

Solution 2

You can not directly change the x value of a CGPoint(or any value of a struct) like that, if it is an property of an object. Do something like the following.

CGPoint _center = blackKey.center;
_center.x =  (whiteKey.frame.origin.x + whiteKey.frame.size.width);
blackKey.center = _center;

Solution 3

blackKey.center = CGPointMake ( whiteKey.frame.origin.x + whiteKey.frame.size.width, blackKey.center.y);

One way of doing it.

Share:
36,311
Mahir
Author by

Mahir

Updated on July 09, 2022

Comments

  • Mahir
    Mahir almost 2 years

    In a piano app, I'm assigning the coordinates of the black keys. Here is the line of code causing the error.

    'blackKey' and 'whiteKey' are both customViews

    blackKey.center.x = (whiteKey.frame.origin.x + whiteKey.frame.size.width);
    
  • EmptyStack
    EmptyStack over 12 years
    We can set anObject.anNonStructProperty.anProperty = someValue right? How do you say that we can not modify the return value of a function. Can you please explain?
  • Chuck
    Chuck over 12 years
    @EmptyStack: When you write anObject.someProperty = something, that is not equivalent to [anObject someProperty] = something — instead, it's equivalent to [anObject setSomeProperty:something]. You're sending a message to the object to call a setter method. You aren't assigning to the method's return value. The appearance of an assignment is just syntactic sugar, just like the appearance of a member access is syntactic sugar for a getter method.
  • Adithya
    Adithya almost 10 years
    I still don't get it clearly. Even in your answer, blackKey.center internally calls objc_msgSend(blackKey, @selector(setCenter:)) and not objc_msgSend(blackKey, @selector(center)) right?
  • Chuck
    Chuck almost 10 years
    @Adithya: No. If you think blackKey.center calls setCenter:, then what do you imagine the argument is? [blackKey setCenter: ?????]. It's just [blackKey center].
  • Nicolas Miari
    Nicolas Miari over 8 years
    Do you really need the do ... while(0)? Isn't the block scope { ... } enough to declare the temp variables (without potentially name-colliding with something just outside), and have the statements within executed exactly once?
  • ThomasW
    ThomasW over 8 years
    @NicolasMiari I've been using do ... while(0) for such a long time that I didn't realize that {...} blocks work just fine. Thanks. Simplifying.
  • ThomasW
    ThomasW over 8 years
    The reasoning for the do ... while(0) is here: stackoverflow.com/questions/154136/… For my case it isn't necessary, but there are cases where it is.