Why I don’t like the frame property

CGRect is the type for the frame property in UIViews.
Which is a c struct defined in CGGeometry.h as the following:

struct CGRect {
  CGPoint origin;
  CGSize size;
};
typedef struct CGRect CGRect

What’s wrong with frame and CGRect? I mean they were written by Apple!

I position and resize views all the time, but I very rarely do it at the same time. What I mean is I might move the view to the position (100, 50), but maintain the size. This is how:

// method 1: use the original frame
// I have 3 lines of code for 1 task
CGRect frame = view.frame;
frame.origin = CGPointMake(100, 50);
view.frame = frame;

// method 2: recreate the frame rect
// I must pass the width and height
view.frame = CGRectMake(100, 50, view.frame.size.width, view.frame.size.height);

// method 3: not legal, but how I want to do it
view.frame.origin = CGPointMake(100, 50);

It might seem I’m complaining about writing a couple extra lines of code. But currently I’m updating the whiteboard feature in my app, which is over 2500 lines of code. The extra lines are not a hassle, they are just adding more mess to scroll past, along with affecting readability.

So if CGRect was a class, it would be able to comply with KVO. As far as I know, this is the reason the frame property not assignable. This means I could change the values of the CGRect and the view can be notified to redraw. Note: the setFrame method of UIView doesn’t just set a value, but instead lets the view know to redraw with a new size.

I’m not going to end my post with just that. Here’s a solution:

// include this function in a class, or in the prefix file
CGRect CGRectMoveOrigin(CGRect rect, CGFloat x, CGFloat y)
{
  CGRect rect;
  rect.origin.x = x;
  rect.origin.y = y;
  return rect;
}

// example
view.frame = CGRectMoveOrigin(view.frame, 100, 50);

// if CGRect were KVO compliant
view.frame.origin.x = 100;
view.frame.origin.y = 50;

I am aware of CGRectOffset, but what if I don’t want to do inline math to change the position? 🙂

In the end, I’m not actually going to use my method, now. I might in future projects. There are a lot of times where I’m only changing one of the 4 values in the CGRect, which would imply I want a ton more CGRectXXX(CGRect frame, ….) functions, and I don’t want that.

But direct access to the frame’s struct would be nice.

Leave a Reply

Your email address will not be published. Required fields are marked *