43

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
  • 37,241
  • 25
  • 195
  • 267
Mahir
  • 1,684
  • 5
  • 31
  • 59
  • 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

83

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
  • 234,037
  • 30
  • 302
  • 389
  • 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,274
  • 23
  • 147
  • 178
10
blackKey.center = CGPointMake ( whiteKey.frame.origin.x + whiteKey.frame.size.width, blackKey.center.y);

One way of doing it.

Dair
  • 15,910
  • 9
  • 62
  • 107
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,981
  • 4
  • 79
  • 106
  • 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.

冯剑龙
  • 569
  • 8
  • 22