NSRect and CGRect conversion
Tuesday night I gave a talk at Chicago Cocoaheads about Core Image. I’ll post the slides and code up later this week, but I wanted to share a quick tip on converting NSRects
to CGRects
and vice versa. An NSRect
is used in Cocoa, and a CGRect
is used in Core Graphics and Core Image. So, if you’re writing Cocoa code, you may have to do many conversions from one to the other. There are various techniques for dealing with this. Since these structures are identical (both are 4 floats
, origin followed by size), you can use a cast:
NSRect bounds = [self bounds]
callSomeCoreGraphicsFunction(*(CGRect *)&bounds);
But this is rather ugly. My personal favorite is the union:
typedef union
{
NSRect nsrect;
CGRect cgrect;
} NSCGRect;
// ...
NSCGRect bounds = { .nsrect = [self bounds] };
callSomeCoreGraphicsFunction(bounds.cgrect);
This uses the nifty C99 union initializer, so you can choose which union element to initialize. In C89, you could only initialize the first element. But since both the union and the cast assume the data structures are identical, I suppose the proper way is to make a new structure:
NSRect bounds = [self bounds];
callSomeCoreGraphicsFunction(
CGRectMake(bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height));
But that’s just such a pain in the butt to write, I’ll use the union, and hope they never change the structures.
UPDATE Mar-16-2007: A little birdie told me that there is a fourth alternative on 10.5. I have confirmed this, but cannot reveal any details due to the Leopard NDA.
UPDATE Jan-3-2008: I realized I never updated this for Leopard. Check out the new NSRectFromCGRect
and NSRectToCGRect
functions in Foundation. Internally, they use the casting method.
UPDATE Sep-21-2008: Matt Gallagher wrote to me a while back to tell me that while Apple’s documentation says they use the casting method, if you look at the NSGeometry.h
header file, they are actually using the union method. The reason is that the cast method does not work with -fstrict-aliasing
enabled. For a more detailed reason why this does not work, read Matt’s post on type punning.