This question was originally asked for the objective-c programming language. At the time of writing, swift didn't even exist yet.
Is it possible to change only one property of a CGRect
?
For example:
self.frame.size.width = 50;
instead of
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, 50);
of course I understand that self.frame.size.width
is read only so I'm wondering how to do this?
CSS ANALOGY proceed at your own risk
for those of you who are familiar with CSS
, the idea is very similar to using:
margin-left: 2px;
instead of having to change the whole value:
margin: 5px 5px 5px 2px;
Frame refers to the coordinate system of the view's container (parent view). Bounds refer to the own coordinate system of the view.
1) Control-drag from a frame view (e.g. questionFrame) to main View, in the pop-up select "Equal heights". 2)Then go to size inspector of the frame, click edit "Equal height to Superview" constraint, set the multiplier to 0.7 and hit return.
Since frame relates a view's location in its parent view, you use it when you are making outward changes, like changing its width or finding the distance between the view and the top of its parent view. Use the bounds when you are making inward changes, like drawing things or arranging subviews within the view.
A structure that contains the location and dimensions of a rectangle.
To answer your original question: yes, it's possible to change just one member of a CGRect
structure. This code throws no errors:
myRect.size.width = 50;
What is not possible, however, is to change a single member of a CGRect
that is itself a property of another object. In that very common case, you would have to use a temporary local variable:
CGRect frameRect = self.frame; frameRect.size.width = 50; self.frame = frameRect;
The reason for this is that using the property accessor self.frame = ...
is equivalent to [self setFrame:...]
and this accessor always expects an entire CGRect
. Mixing C-style struct
access with Objective-C property dot notation does not work well in this case.
I liked Ahmed Khalaf's answer, but it occurred to me that you may as well just write out a few C functions... the key advantage being that it'll be easier to track down errors in the event that you're using the wrong type.
Having said that, I wrote a .h file with these function declarations:
CGRect CGRectSetWidth(CGRect rect, CGFloat width); CGRect CGRectSetHeight(CGRect rect, CGFloat height); CGRect CGRectSetSize(CGRect rect, CGSize size); CGRect CGRectSetX(CGRect rect, CGFloat x); CGRect CGRectSetY(CGRect rect, CGFloat y); CGRect CGRectSetOrigin(CGRect rect, CGPoint origin);
And a corresponding .m file with these function implementations:
CGRect CGRectSetWidth(CGRect rect, CGFloat width) { return CGRectMake(rect.origin.x, rect.origin.y, width, rect.size.height); } CGRect CGRectSetHeight(CGRect rect, CGFloat height) { return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, height); } CGRect CGRectSetSize(CGRect rect, CGSize size) { return CGRectMake(rect.origin.x, rect.origin.y, size.width, size.height); } CGRect CGRectSetX(CGRect rect, CGFloat x) { return CGRectMake(x, rect.origin.y, rect.size.width, rect.size.height); } CGRect CGRectSetY(CGRect rect, CGFloat y) { return CGRectMake(rect.origin.x, y, rect.size.width, rect.size.height); } CGRect CGRectSetOrigin(CGRect rect, CGPoint origin) { return CGRectMake(origin.x, origin.y, rect.size.width, rect.size.height); }
So, now, to do what you want, you can just do:
self.frame = CGRectSetWidth(self.frame, 50);
Get even Fancier (update I made a year later)
This has a redundant self.frame
in it, though. To fix that, you could add a category
on UIView
with methods that look like this:
- (void) setFrameWidth:(CGFloat)width { self.frame = CGRectSetWidth(self.frame, width); // You could also use a full CGRectMake() function here, if you'd rather. }
And now you can just type in:
[self setFrameWidth:50];
Or, even better:
self.frameWidth = 50;
And just so you can do something like this:
self.frameWidth = otherView.frameWidth; // as opposed to self.frameWidth = otherView.frame.size.width;
You'll need to also have this in your category:
- (CGFloat) frameWidth { return self.frame.size.width; }
Enjoy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With