Fun with CGRect
I saw this post on Dr. Touch today on CGRect tricks. Very good stuff, as he mentions, CGRect is probably one of the most used structures in iPhone programming, especially when doing UI work, since the frame property of UIView is the basis for determining how things are laid out on screen.
Dr. Touch’s article goes over the following, read his article for more on these subjects:
- Creating with CGRectMake()
- Transforming with CGRectInset() and UIEdgeInsetsInsetRect()
- Intersection tests with CGRectContainsPoint() and CGRectIntersectsRect()
- Creating and loading from a dictionary representation with CGRectCreateDictionaryRepresentation() and CGRectMakeWithDictionaryRepresentation()
The topic of CGRect is on my list of blog post ideas, so I’ll go ahead and add a couple of my own CGRect tricks I’ve found useful.
Null, Empty/Zero, and Infinite rectangles
There are three CGRect constants that can come in useful: CGRectNull, CGRectZero and CGRectInfinite. These are matched by three comparison functions, CGRectIsNull(), CGRectIsEmpty(), CGRectIsInfinite().
CGRectNull and CGRectIsNull() deal with the concept of the null set, i.e. the result of unioning two disjoint rectangles. CGRectInfinite and CGRectIsInfinite() are all about a rectangle with no bounds.
There is a subtle difference between the functionality of CGRectZero and CGRectIsEmpty(). CGRectZero is simply a rect with an origin of 0,0 and a size of 0. CGRectIsEmpty(), however, returns true for either CGRectZero or CGRectNull, which is an important distinction to make.
Comparing CGRects
Since CGRect is a structure, comparing for equality isn’t as simple as
if(rectA == rectB)
But never fear, CGRectEqualToRect() is here! CGRectEqualToRect() compares to CGRects, and returns a bool letting you know if they are equivalent (equivalent in this context meaning the two rectangles have the same origin, and the same size).
Here’s a snippet of example code:
//is the tab bar controller's frame the same as when we initialized?
if(!CGRectEqualToRect(tabBarController.view.frame,tabBarFrame))
{
//then we whip it into shape.
tabBarController.view.frame = tabBarFrame;
}
The problem being solved here was that the frame of a UITabBarController was being mysteriously being reset by “mysterious forces” (which turned out to be presentModalViewController:animated:). The above snipped of code is called when a change in the frame is observed, forcing the frame back to a state I specified during initialization.
CGRectUnion is UIScrollView’s best friend
So here’s the scenario: you have a UIScrollView with a bunch of subviews, which can dynamically resize and lay themselves out. That’s all well and good, but how do you set the contentSize of the scroll view so that the user can see all the subviews?
If you know the top-left most and bottom-right most view, the answer is simple, use those points to define a rectangle, then add some padding. Which in Core Graphics terms, means CGRectUnion() and CGRectInset():
// get the rectangle that encompasses all of the dynamic content CGRect theUnion = CGRectUnion(topLeftView.frame, bottomRightView.frame); // add some padding to top and bottom (negative value adds padding, positive is an inset) CGRect paddedUnion = CGRectInset(theUnion, 0, -20); // in the end, we really only need the size of the rect contentScroller.contentSize = paddedUnion.size;
Easy enough!



