views:

29

answers:

2

Lets say that I want to temporarily change the frame of a view (for eg move it 10px to the right - probably in connection with highlighting a change).

I assumed the psuedo code would be something like

self.someView.frame.origin.x += 10.0f;

But this gives me an error of

lvalue required as left operand of assignment

So what I do instead is make a new CGRect to represent the frame, alter that CGRect then give the view the CGRect as it's frame

CGRect aFrame = self.someView.frame;
aFrame.origin.x += 10.0f;
[self.someView setFrame:aFrame];

Seems funny that I can make an assignment on a CGRect, but not on a view's frame which is a CGRect.

So, is this the best way to alter a frame for an existing view?

And for bonus points: Why can't I assign a new value directly on the view's frame property, why do I have to beat 'round the bushes like this?

Thanks

+1  A: 

Answering this question answers for bonus points, as well. It's all about getters & setters.

self.someView.frame is a getter--it returns the frame & goes no deeper. It doesn't allow you to reach into the CGRect and alter values.

Thus:

CGRect r = self.someView.frame;
r.origin.x += 10.0f;
self.someView.frame = r;

This is, no doubt, confusing if coming from a language where dot-notation is the typical way of getting & setting values regardless of context. Objective C dot-notation can be confusing in unforseen ways because Obj-C can invoke methods via dot syntax as well as get property values. Thus, there's no simple way of knowing that self.someView.frame is really self.someView.frame() (to use a Pythonic syntax).

Not to sound annoying (really, I program Python daily), but you're really not beating around the bushes using the standard message-passing syntax of Obj-C. You can definitely leverage dot syntax to save yourself some steps, but bracketed message-passing has a certain amount of self-documenting helpfulness and helps you avoid such errors.

bobwaycott
Makes sense now, thanks bobwaycott. I come from a Ruby background so on that level I assumed that since I could see the values in the rect I could change them. I now understand why I can't. Thanks for your answer.
davidamcclain
+3  A: 

And for bonus points: Why can't I assign a new value directly on the view's frame property, why do I have to beat 'round the bushes like this?

Because the dot notation is used for 2 different use cases here: property access and struct member access. Another way to write

self.someView.frame.origin.x += 10.0f;

would be

[[self someView] frame].origin.x += 10.0f;

This line makes it clearer that this can't work. [[self someView] frame] retrieves a CGRect but if you would change a member of this struct, the contents of the frame property itself would not be changed. To assign something to the frame property, the -setFrame: method must be used. And -setFrame always requires an entire CGRect as its argument.

Ole Begemann
Thanks Ole. I see now that since the frame property of the view is set to receive a CGRect, that same property wouldn't be set up to know anything about how a CGRect works. The rect is just a value to be passed to it. If I pull out the frame into it's own var then it knows all about how CGRects work so I can manipulate the struct. Light bulb moment!
davidamcclain