Fast enumeration on 10.4

Tomorrow I’m showing some software I wrote to a client, and I don’t want to lug the external Harddrive on which Leopard is installed with me. The laptop still runs 10.4 for testing Find It! Keep It!

The software uses fast enumeration on arrays and sets. Building with the Mac OS 10.5 SDK and with 10.4 as deployment target worked, but running the code on 10.4 failed. The method countByEnumeratingWithState:objects:count: was missing. So I thought I’d add it — I stole its implementation from Cocotron, and added conditional posing for 10.4 systems:


// Stolen from Cocotron

#import <AppKit/AppKit.h>

@interface NSArrayEX : NSArray
@end


@implementation NSArrayEX

+ (void) load
{
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

  OSErr err;
  SInt32 systemVersion;
  if ((err = Gestalt(gestaltSystemVersion, &systemVersion)) == noErr)
    if ((systemVersion & 0xfff0) == 0×1040)
      [self poseAsClass:[NSArray class]];

  [pool release];
}


-(NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)length;
{
  int numObjects=MIN([self count] - state->extra[0], length);
  int i=state->extra[0];
  int j=0;
  state->itemsPtr=stackbuf;

  for(j=0; j<numObjects; j++, i++)
    state->itemsPtr[j]=[self objectAtIndex:i];

  state->extra[0]+=numObjects;

  state->mutationsPtr=(unsigned long *)self;

  return numObjects;
}

@end




@interface NSSetEX : NSSet
@end


@implementation NSSetEX

+ (void) load
{
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

  OSErr err;
  SInt32 systemVersion;
  if ((err = Gestalt(gestaltSystemVersion, &systemVersion)) == noErr)
    if ((systemVersion & 0xfff0) == 0×1040)
      [self poseAsClass:[NSSet class]];

  [pool release];
}



-(NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)length;
{
  int i;
  state->itemsPtr=stackbuf;
  
  state->mutationsPtr=(unsigned long*)self;
  if(!state->state)
    state->state=(unsigned long)[self objectEnumerator];

  id en=(id)state->state;
  
  for(i=0; i<length; i++)
  {
    state->itemsPtr[i]=[en nextObject];
    if(!state->itemsPtr[i])
      return i;
  }

  return i;
  
}

@end

It works surprisingly well. Unfortunately I then discovered that you can only create a 16 bit grey image context on 10.5 Oh well.

(Sorry for the horrible layout — I don’t have the time to dink with Wordpress right now)

2 Responses to “Fast enumeration on 10.4”

  1. Jordy/Jediknil Says:

    Wait…why not just use a category? You’re not trying to override existing behavior (at least, not on 10.4).

  2. sengan Says:

    As you say, because I don’t want to override existing behaviour on 10.5.

Leave a Reply