Tuesday, June 29, 2010

Sending Messages to nil is Not Always Safe

I've been under the impression that in Objective-C sending messages to nil was always safe but learned recently that it is not always the case and wanted to share.

The conventional Objective-C wisdom says that sending messages to nil is safe (it acts as a noop) and returns nil for object return values and 0 or zero filled structs for scalar or struct return values.

As it turns out some scalars / structs will not be zeroed out which means they will contain random data.

The language Apple uses in their docs say that scalars are guaranteed to be zero only if the size of the return type is "less than or equal to sizeof(void*)" or the returned struct is "to be returned in registers" as "defined by the Mac OS X ABI Function Call Guide".

CGRect is an example of one that does not meet this criteria. As an example the following code:

UIViewController *viewController = nil;
UIView *view = [viewController view];
CGRect frame = [view frame];
NSLog(@"frame=%@", NSStringFromCGRect(frame));
will print out something like this:
frame={{1.6584e-37, -1.99876}, {6.19141e-39, 6.05479e-37}}
Long story short, take care when calling methods that return scalars / structs if the object you are messaging could be nil.

A good blog post on the topic is here:
http://vgable.com/blog/2008/05/31/messages-to-nowhere

In it he points out that the behavior can vary by platform / processor so what happens on the iPhone simulator may not be what happens on the actual device.

Saturday, June 19, 2010

Don't Draw At Fractional Pixel Locations

In the Objective-C Cocoa and Cocoa Touch APIs positions and sizes of UI elements are specified in terms of CGFloats but as I recently discovered problems can occur if you use non-integral values.

One symptom you may find is that with anti-aliasing on the text of a UILabel will appear blurry if the position is set with a fractional value.

The function CGRectIntegral() can help with this.