iOS frame change one property (eg width) iOS frame change one property (eg width) ios ios

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;}