HKIndexSetEnumerator
I have often been annoyed by NSIndexSet -- Apple has pretty much coerced its use by deprecating perfectly good methods in several classes, leaving only the NSIndexSet versions available.
My core grumble with NSIndexSet is that it is not a subclass of NSSet, and so is missing some useful functionality. The functionality I miss the most is the ability to enumerate.
So I added an index set enumerator class, and a category on NSIndexSet to create the enumerator.
-------------- Interface -------------
#import <Cocoa/Cocoa.h>
@interface HKIndexEnumerator : NSObject
{
int _currentIndex;
unsigned _lastGoodIndex;
NSIndexSet * _indexSet;
}
/*
SPECIAL BEHAVIORS (mostly to emulate standard enumerator behavior):
if you first call nextIndex, you start with firstIndex.
If you first call previousIndex, you start with lastIndex (wrap-around)
(I didn’t bother with a reverse enumerator, instead I implemented reverse enumeration directly)
If you "run off the end", you can back into the indices with the inverse enumeration message:
if((idx = [thing nextIndex]) == NSNotFound)
{
idx = [thing previousIndex];
}
if((idx = [thing previousIndex]) == NSNotFound)
{
idx = [thing nextIndex];
}
*/
- (unsigned) nextIndex; //NSNotFound if exhausted
- (unsigned) previousIndex; //NSNotFound if exhausted
- (unsigned) firstIndex;
- (unsigned) lastIndex;
// autoreleased c-array of unsigned ints.
// Can be prohibitively large if used carelessly.
// Must be copied if you need it beyond the current pool.
- (unsigned *) allIndices;
+ (HKIndexEnumerator *) indexEnumeratorForIndexSet: (NSIndexSet *) indexSet;
- (void) reset; // resets to initial state
@end
@interface NSIndexSet (IndexEnumerator)
- (HKIndexEnumerator *) indexEnumerator;
@end
-------------- Implementation -------------
#import "HKNSIndexEnumerator.h"
@implementation NSIndexSet (IndexEnumerator)
- (HKIndexEnumerator *) indexEnumerator
{
// note that you cannot blithely subclass HKIndexEnumerator.
return [HKIndexEnumerator indexEnumeratorForIndexSet: self];
}
@end
@implementation HKIndexEnumerator
- (NSIndexSet*)indexSet
{
return _indexSet;
}
- (void)setIndexSet:(NSIndexSet*)inIndexSet
{
if (_indexSet != inIndexSet) {
[_indexSet release];
_indexSet = [inIndexSet retain];
}
}
- (void) dealloc
{
[self setIndexSet: nil];
[super dealloc];
}
- (unsigned) nextIndex
{
unsigned result = NSNotFound;
if(_currentIndex == -1)
{
_currentIndex = result = [[self indexSet] firstIndex];
}
else
{
if(_currentIndex == NSNotFound)
{
if(_lastGoodIndex == [[self indexSet] firstIndex])
{
_currentIndex = _lastGoodIndex;
}
result = _currentIndex;
}
else
{
result = [[self indexSet] indexGreaterThanIndex: _currentIndex];
if((result == NSNotFound) && (_currentIndex != NSNotFound) )
{
_lastGoodIndex = _currentIndex;
}
_currentIndex = result;
}
}
return result;
}
- (unsigned) previousIndex
{
unsigned result = NSNotFound;
if(_currentIndex == -1)
{
_currentIndex = result = [[self indexSet] lastIndex];
}
else
{
if(_currentIndex == NSNotFound)
{
if(_lastGoodIndex == [[self indexSet] lastIndex])
{
_currentIndex = _lastGoodIndex;
}
result = _currentIndex;
}
else
{
result = [[self indexSet] indexLessThanIndex: _currentIndex];
if((result == NSNotFound) && (_currentIndex != NSNotFound) )
{
_lastGoodIndex = _currentIndex;
}
_currentIndex = result;
}
}
return result;
}
- (unsigned) firstIndex
{
unsigned result = _currentIndex = [[self indexSet] firstIndex];
return result;
}
- (unsigned) lastIndex
{
unsigned result = _currentIndex = [[self indexSet] lastIndex];
return result;
}
- (unsigned *) allIndices
{
unsigned indicesCount = [[self indexSet] count];
NSMutableData * dataBlock = [NSMutableData dataWithLength: indicesCount * sizeof(unsigned)];
[[self indexSet] getIndexes:[dataBlock mutableBytes] maxCount: indicesCount inIndexRange: nil];
return [dataBlock mutableBytes];
}
- (id) initWithIndexSet: (NSIndexSet *) indexSet
{
if((self = [super init]))
{
if(!indexSet)
{
self = nil;
}
else
{
[self setIndexSet: [[indexSet copy] autorelease]];
_currentIndex = -1;
}
}
return self;
}
- (void) reset
{
_currentIndex = -1;
}
+ (HKIndexEnumerator *) indexEnumeratorForIndexSet: (NSIndexSet *) indexSet
{
return [[[self alloc] initWithIndexSet: indexSet] autorelease];
}
@end
• While fact-based, the contents of this website is 100% opinion • All advertisements Selected By Google Ad Sense • Your Mileage May Vary • Void Where Prohibited • Do Not Try This At Home • Don’t Be An Idiot •