objective-cnsenumerator

What is the value of NSEnumerator?


when for . . . in . . . is available?

Specifically, when we can write:

NSArray *array;
// array allocated and initialized here.
for (id obj in array) {
  // do something to the object here
}

Why would we ever use an NSEnumerator?


Solution

  • NSEnumerator was created before fast enumeration (for/in loop) was available. Think of it as backward-compatibility if you like.

    But with NSEnumerator you can enumerate the collection in customized order, e.g. backwards:

    NSEnumerator* enu = [array reverseObjectEnumerator];
    id object;
    while ((object = [enu nextObject])) {
     ...
    }
    

    (Of course, since NSEnumerator also supports for/in loop you can use a better way:

    for (id object in [array reverseObjectEnumerator]) {
      ...
    }
    

    )

    or define your own iterator class by subclassing NSEnumerator, e.g.

    #import <Foundation/Foundation.h>
    
    @interface RangeEnumerator : NSEnumerator {
        int cur, len;
    }
    +(RangeEnumerator*)enumeratorWithLength:(int)length;
    -(id)initWithLength:(int)length;
    -(id)nextObject;
    @end
    @implementation RangeEnumerator
    -(id)initWithLength:(int)length {
        if ((self = [super init]))
            len = length;
        return self;
    }
    +(RangeEnumerator*)enumeratorWithLength:(int)length {
        return [[(RangeEnumerator*)[self alloc] initWithLength:length] autorelease];
    }
    -(id)nextObject {
        if (cur < len)
            return [NSNumber numberWithInt:cur++];
        else
            return nil;
    }
    @end
    
    int main () {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    
        for (NSNumber* num in [RangeEnumerator enumeratorWithLength:12])
            printf("%d\n", [num intValue]);
    
        [pool drain];
    
        return 0;
    }