18

It may sound very silly to people who know this but I am quite new to iOS. I wanted to know, why cant we modify origin or size or may be x,y or height width of these properties of a UIView frame ?

frame is a CGRect struct and origin and size are again CGPoint and CGSize structures. when we can access them, why cant we modify them ?

There is nothing like this in a CGRect, we can modify it's attributes so why cant we do it for frame or bounds.

Amogh Talpallikar
  • 12,084
  • 13
  • 79
  • 135
  • Great question, not silly at all! – Chris Nolet Oct 29 '14 at 04:07
  • 1
    @ChrisNolet: It's been more than two years since I posted this! – Amogh Talpallikar Oct 29 '14 at 04:10
  • 2
    After 4 years of doing iOS, I finally understand why I can't set the frame directly! – Chris Nolet Oct 29 '14 at 04:21
  • The reason is he entire frame is writable/assignable while single properties not (only readble) – doxsi Nov 15 '17 at 12:48
  • I wrote an extension in Swift that lets you set a views frame to any specified origin. I did a little math and figured out where the center position needs to be in order to get the desired origin. The extension technically still sets the center property (adjusted to get the desired origin) ! See https://stackoverflow.com/questions/10012406/how-to-set-a-uiviews-origin-reference/65324896#65324896 – user3408691 Dec 16 '20 at 14:33

2 Answers2

26

I assume you mean why can't you do somethIng like this:

myView.frame.origin.x = 23.0;

It's a good question, nothing silly about it. The problem is that the frame is held as the property of the view, not the individual components of the frame (the size and origin, or even deeper, the width, length, x and y).

The frame is fundamental to the view, so there are lots of actions that a view needs to do if its frame is modified. If you were to reach in and modify the origin.x directly then you would be bypassing the setFrame method where all of this magic probably happens.

When you access view.frame you are being given a CGRect that has the same value as view.frame, but is not actually the frame, so any modifications to it don't affect the view.

You can do it in steps:

CGRect frame = view.frame;
frame.origin.x = 23.0;
view.frame = frame;
jrturton
  • 118,105
  • 32
  • 252
  • 268
  • Thanks for the answer and not considering it silly. But I do feel silly after understanding it. i hope anyone having a similar doubt will find this helpful. – Amogh Talpallikar Feb 23 '12 at 12:05
  • 1
    Sorry, I still don't get it. OK, by `view.frame` we get a C struct that isn't the real `view.frame`. Isn't it simpler to just say we get a copy? OK, so we get a copy. Why need a copy anyway? – Philip007 Nov 05 '12 at 20:00
  • doesn't answer anything on why updating origin / size can't update the frame ? – Yugal Jindle Mar 03 '18 at 20:30
10

The answer lies in the (slightly obfuscated) language syntax:

  1. myView is an Objective-C object.
  2. So myView.frame is a property accessor method being send.
  3. It returns a C struct of type CGRect.
  4. frame.origin.x = 1 modifies the returned temporary struct that is local to your code.

Your intent was to tell an object something by sending it a message. But instead you asked the object for data and then modified this data. The object would never now.

The compiler should warn you about this error.

Nikolai Ruhe
  • 81,520
  • 17
  • 180
  • 200