Vincent Gable’s Blog

December 28, 2008

Fast Enumeration In Objective-C 1.0

Filed under: Cocoa,MacOSX,Objective-C,Programming,Sample Code | , ,
― Vincent Gable on December 28, 2008

I have used ForEach.h to do “Fast Enumeration” in Mac OS X 10.4 “Tiger”, without any problems. You must set the “C Language Dialect” in Xcode to C99 for it to work. Credit to Michael Tsai for the code, you can find other implementations of it on his website.

With ForEach.h you can do:

#import "ForEach.h"

foreach(thing, collection) {
   /*do stuff with thing*/
}

foreacht(NSString, name, allNames)
   ;//name is typed as an NSString*

With a large collection, the foreach macro should be faster then using NSEnumerator or objectAtIndex:, because it calls the nextObject function directly, without going through Objective-C’s message sending. I have not benchmarked it, because I haven’t had a reason to optimize the mechanics of my for-loops, so I don’t know by how much. But it should give you the fast in Fast Enumeration.

If you can’t use Objective-C 2.0’s Fast Enumeration (requires Leopard or, iPhone), then I highly recommend ForeEach.h.

May 31, 2008

Messages to Nowhere

Filed under: Bug Bite,Cocoa,iPhone,MacOSX,Objective-C,Programming | , , ,
― Vincent Gable on May 31, 2008

If you send a message to (call a method of) an object that is nil (NULL) in Objective-C, nothing happens, and the result of the message is nil (aka 0, aka 0.0, aka NO aka false). At least most of the time. There is an important exception if sizeof(return_type) > sizeof(void*); then the return-value is undefined under PowerPC/iPhone, and thus all Macs for the next several years. So watch out if you are using a return value that is a struct, double, long double, or long long.

The fully story:

In Objective-C, it is valid to send a message to a nil object. The Objective-C runtime assumes that the return value of a message sent to a nil object is nil, as long as the message returns an object or any integer scalar of size less than or equal to sizeof(void*).
On Intel-based Macintosh computers, messages to a nil object always return 0.0 for methods whose return type is float, double, long double, or long long. Methods whose return value is a struct, as defined by the Mac OS X ABI Function Call Guide to be returned in registers, will return 0.0 for every field in the data structure. Other struct data types will not be filled with zeros. This is also true under Rosetta. On PowerPC Macintosh computers, the behavior is undefined.

I was recently bitten by this exceptional behavior. I was using an NSRange struct describing a substring; but the string was nil, so the substring was garbage. But only on a PPC machine! Even running under Rosetta wouldn’t have reproduced the bug on my MacBook Pro.Undefined values can be a hard bug to detect, because they may be reasonable values when tests are run.

Code running in the iPhone simulator will return all-zero stucts when messaging nil, but the same code running on an actual device will return undefined structs. Be aware that testing in the simulator isn’t enough to catch these bugs.

A few simple guidelines can help you avoid my misfortune:

  • Be especially careful using of any objective-C method that returns a double, struct, or long long
  • Don’t write methods that return a double, struct, orlong long. Return an object instead of a struct; an NSNumber* or float instead of a double or long long. If you must return a dangerous data type, then see if you can avoid it. There really isn’t a good reason to return a struct, except for efficiency. And when micro-optimizations like that matter, it makes more sense to write that procedure in straight-C, which avoids the overhead of Objective-C message-passing, and solves the undefined-return-value problem.
  • But if you absolutely must return a dangerous data type, then return it in a parameter.
    Bad:
    - (double) crazyMath;
    Good:
    - (void) crazyMathResult:(double*)result;.

I love Objective-C’s “nil messaging” behavior, even though it is rough around the edges. It’s usefulness is beyond the scope of this article, but it can simplify your code if you don’t return a data-type that is larger then sizeof(void*). With time, when the intel-style return behavior can be universally relied on, things will be even better.

February 26, 2008

this is Confusing, self is Not

Filed under: C++,Objective-C,Programming,Usability | , ,
― Vincent Gable on February 26, 2008

Most diction decisions, like choosing the keyword nil over NULL seem inconsequential. Sure, n-i-l is probably faster to type then shift+n-u-l-l, but the difference is too small to matter. Both terms are clear.

However after today I’m convinced that the C++ convention of using the keyword this, over self, was a mistake. “This” is just too common of a pronoun. It’s too easy to say something like “..this is invalid..”, and leave people wondering if you meant that-this or self-this.

I’d be interested to know the reasoning behind choosing the ambiguous keyword “this” over the precedent “self”.

I plan to refer to “this” as “self” whenever possible for a time, to see if it’s less confusing, even to habitual C++ users.

Powered by WordPress