iOS frame change one property (eg width)
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.
Based on ArtOfWarfare's solution (which is really awesome) I've build the UIView
category without C-functions.
Usage examples:
[self setFrameWidth:50];self.frameWidth = 50;self.frameWidth += 50;self.frameWidth = otherView.frameWidth; // as opposed to self.frameWidth = otherView.frame.size.width;
Header file UIView+easy_frame.h
:
@interface UIView (easy_frame)- (void) setFrameWidth:(CGFloat)width;- (void) setFrameHeight:(CGFloat)height;- (void) setFrameX:(CGFloat)x;- (void) setFrameY:(CGFloat)y;- (CGFloat) frameWidth;- (CGFloat) frameHeight;- (CGFloat) frameX;- (CGFloat) frameY;
Implementation file UIView+easy_frame.m
:
#import "UIView+easy_frame.h"@implementation UIView (easy_frame)# pragma mark - Setters- (void) setFrameWidth:(CGFloat)width{ self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, width, self.frame.size.height);}- (void) setFrameHeight:(CGFloat)height{ self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, height);}- (void) setFrameX:(CGFloat)x{ self.frame = CGRectMake(x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);}- (void) setFrameY:(CGFloat)y{ self.frame = CGRectMake(self.frame.origin.x, y, self.frame.size.width, self.frame.size.height);}# pragma mark - Getters- (CGFloat) frameWidth{ return self.frame.size.width;}- (CGFloat) frameHeight{ return self.frame.size.height;}- (CGFloat) frameX{ return self.frame.origin.x;}- (CGFloat) frameY{ return self.frame.origin.y;}