41

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);
Cœur
  • 34,719
  • 24
  • 185
  • 251
Mahir
  • 1,654
  • 5
  • 31
  • 58
  • Note that `whiteKey.frame.origin.x + whiteKey.frame.size.width` is the same as `CGRectGetMaxX(whiteKey.frame)`. – ThomasW Sep 09 '15 at 03:31

5 Answers5

82

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.

Chuck
  • 228,856
  • 29
  • 291
  • 386
  • 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? – EmptyStack Aug 16 '11 at 07:02
  • 4
    @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. – Chuck Aug 16 '11 at 07:28
  • 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? – Adithya Jul 22 '14 at 10:24
  • @Adithya: No. If you think `blackKey.center` calls `setCenter:`, then what do you imagine the argument is? `[blackKey setCenter: ?????]`. It's just `[blackKey center]`. – Chuck Jul 22 '14 at 17:22
19

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;
EmptyStack
  • 51,114
  • 22
  • 146
  • 177
10
blackKey.center = CGPointMake ( whiteKey.frame.origin.x + whiteKey.frame.size.width, blackKey.center.y);

One way of doing it.

Dair
  • 15,412
  • 8
  • 59
  • 104
0

One alternative using macros:

#define CGPOINT_SETX(point, x_value) { \
    CGPoint tempPoint = point;         \
    tempPoint.x = (x_value);           \
    point = tempPoint;                 \
}

#define CGPOINT_SETY(point, y_value) { \
    CGPoint tempPoint = point;         \
    tempPoint.y = (y_value);           \
    point = tempPoint;                 \
}

CGPOINT_SETX(blackKey.center, whiteKey.frame.origin.x + whiteKey.frame.size.width);

or slightly simpler:

CGPOINT_SETX(blackKey.center, CGRectGetMaxX(whiteKey.frame));
ThomasW
  • 16,483
  • 4
  • 76
  • 103
  • 1
    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? – Nicolas Miari Sep 09 '15 at 03:35
  • @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 Sep 09 '15 at 03:57
  • 1
    The reasoning for the `do ... while(0)` is here: http://stackoverflow.com/questions/154136/do-while-and-if-else-statements-in-c-c-macros For my case it isn't necessary, but there are cases where it is. – ThomasW Sep 09 '15 at 05:09
0

As its meanings, you can't assign value to expression. For instance, a + b = c it is forbidden.

冯剑龙
  • 520
  • 8
  • 20