The best description of how Cocoa’s views are designed that I could find from Apple is in the Cocoa Views Guide PDF in the chapter called View Geometry. If you’re trying to get your head around what a `CGRect` is and why `self.view.frame.origin.x++` doesn’t work, that’s required reading. (A hint to the latter: view.frame is return-by-value; CGRect is a struct, self is an object.)

That said, here’s a handy graphic to not only help you get your head around when to use `frame` and when to use `bounds`, but also what they mean in the grand scale of things. Also included are some visual guides on when to use some handy `CGGeometry.h` functions to do some work for you.

Caveat emptor: The above describes the iOS coordinate system, which is technically inverted. Mac OS X’s origins are at the lower left (Cartesian quadrant 1) so while all the X-related items are correct, in Mac OS X the Y-related items would be reversed with `CGRectGetMinY` at the bottom.

### Examples

How about some examples? There are also two more functions that are day-savers here. These take in a rect and then spit out a modified rect. Because they act on copies (pass-by-value) you can input one rect and output it somewhere else. How about setting a new view to be a 10pt inset from the current bounds? Easy.

``````(CGRect) CGRectOffset(rect, dx, dy)
``````

Moves the origin of the rect by the delta X and Y.

``````(CGRect) CGRectInset(rect, dx, dy)
``````

Resizes a rect in-place (maintaining the center point) by the delta X and Y. Positive deltas shrink the rect, negative values grow it.

#### Example: Move a view up or down by y.

``````view.frame = CGRectOffset(view.frame, 0, y);
``````

#### Example: Expand a view by 5.0 in three directions (not down).

``````view.frame = CGRectInset(view.frame, -10.0, -5.0);
view.frame = CGRectOffset(view.frame, 0, -5.0);
``````

#### Example: Is a view’s origin on the top half of its superview?

``````BOOL wellIsIt = (CGRectGetMinY(view.frame) < CGRectGetMidY(view.superview.frame))
``````

#### Example: Drag a view around in a `UIPanGestureRecognizer` callback.

Here’s a fun one. Note that you could also pass the resultant point into a transform so that failed drags could simply be an animated reset to an identity transform, but that’s no fun. Keep the original rect around somewhere and then just move it.

``````if (
[gestureRecognizer state] == UIGestureRecognizerStateBegan ||
[gestureRecognizer state] == UIGestureRecognizerStateChanged) {
CGPoint point = [gestureRecognizer translationInView:self.view];
floatyView.frame = CGRectOffset(floatyView.frame, point.x, point.y);
[gestureRecognizer setTranslation:CGPointZero inView:self.view];
}
``````

#### Exercise: Manually convert a point from one coordinate system to another.

This is fun. (For varying degrees of fun.) A point is just an x/y pair; it has no knowledge of from whence it came. So (10,10) to your view is really (38,17) to your superview or (40,17) to its superview. To live in this hellhole of a world, we typically exploit `NSView` or `UIView` and tell them to sort it out like so:

``````[self.view convertPoint:point fromView:someSubview]
``````

But, where’s the fun in that? More importantly: do you know what’s happening?

I’ll let you work on this on your own. You can always get the right answer with the `-convertPoint:fromView:` method so you know the goal to reach. Here’s a hint: figure out if the `fromView` is an ancestor or descendant to you and then crawl the chain of subviews up from the lowest view until you reach the other, calculating the total offset from the `frame` of each, then apply that offset to the point.

Moving a whole rect is similar, but you’re just setting the origin point.

I love this stuff. :)

February 06, 2013