Comparison of Objective-C Enumeration Techniques
If there are multiple contiguous object stores,
NSFastEnumeration
allows the collection to return interior pointers one after another, allowing for a quick loop implementation over each store, and requiring an Objective-C message only for getting the next interior pointer. For collections without contiguous storage,NSFastEnumeration
allows the collection to copy objects out to temporary storage in bulk, reaping many of the same benefits. For collections where none of this works,NSFastEnumeration
still allows a collection to efficiently return objects one by one.…Nice syntax, good performance, it’s a great combination.
Unfortunately, you can’t use fast enumeration if you support Mac OS X 10.4. Currently, I write all my loops using a foreach
macro, which conditionally compiles to IMP-caching and NSEnumerator
under 32 bit and for…in
under 64-bit.
2 Comments RSS · Twitter
Do you have this code for your latest foreach
posted anywhere? I used an earlier version of your macro for a few years, and really loved it! (Fortunately I haven't had to deal with Obj-C 1.0 code lately though, so I've been using the modern for…in.)
@Vincent Gable Here’s the current code:
#if __LP64__ #define foreacht(type, object, collection) \ for (type object in collection) #else #define foreachGetEnumerator(c) \ ([c respondsToSelector:@selector(objectEnumerator)] ? \ [c objectEnumerator] : \ c) #define foreacht(type, object, collection) \ for (id foreachCollection = collection; \ foreachCollection; \ foreachCollection = nil ) \ for (id foreachEnum = foreachGetEnumerator(foreachCollection); \ foreachEnum; \ foreachEnum = nil ) \ for (IMP foreachNext = [foreachEnum methodForSelector:@selector(nextObject)]; \ foreachNext; \ foreachNext = NULL ) \ for (type object = foreachNext(foreachEnum, @selector(nextObject)); \ object; \ object = foreachNext(foreachEnum, @selector(nextObject)) ) #endif #define foreach(object, collection) foreacht(id, object, (collection))
In retrospect, perhaps I should have used OBJC_API_VERSION >= 2
instead of __LP64__
.