Paul Paul - 3 months ago 5x
Objective-C Question

Two lines of code that are saying the same thing?

I am folowing this exercise in a book, and at one point, there is an implementation for a method that creates labels placed at random in the view. Here is the code:

1 - (void)drawHypnoticMessage:(NSString *)message{

2 for(int i =0; i<20; i++){

3 UILabel *messageLabel = [[UILabel alloc] init];

4 messageLabel.backgroundColor = [UIColor clearColor];

5 messageLabel.textColor = [UIColor whiteColor];

6 messageLabel.text = message;

7 [messageLabel sizeToFit];

8 int width = self.view.bounds.size.width - messageLabel.bounds.size.width;

9 int randomX = arc4random() % width;

10 int height = self.view.bounds.size.height - messageLabel.bounds.size.height;

11 int randomY = arc4random() % height;

12 CGRect frame = messageLabel.frame;

13 frame.origin = CGPointMake(randomX, randomY);

14 messageLabel.frame = frame;

15 [self.view addSubview:messageLabel];

16 }

17 }

This works fine. My question is regarding the lines 12 and 14. When I was copying this exercise to xCode from the book and I reached line 12, I instinctively changed it to:

12 CGRect frame;

This didn't work, and I don't understand why. To me, lines 12 and 14:

12 CGRect frame = messageLabel.frame;

14 messageLabel.frame = frame;

Are saying the same thing twice, surely... Can anyone please explain why it is not so? Thanks

Avi Avi

Objective-C overloads C's struct member access operator (.) to also access properties of Objective-C objects. The problem is that you can't mix the two in a single assignment statement because the compiler's parser gets confused.

messageLabel is an object that has a property called frame. frame is a struct with two members: origin and size.

To get around this limitation, you need to use a temporary variable to hold the struct (e.g. frame), manipulate this copy (structs are copied on assignment), and then assign the new struct (frame) to the property, which updates the property's value.