Search code examples
objective-ccocoa-touchcocoansrange

Looping using NSRange


I'm trying to use NSRange to hold a range of years, such as

NSRange years = NSMakeRange(2011, 5);

I know NSRange is used mostly for filtering, however I want to loop over the elements in the range. Is that possible without converting the NSRange into a NSArray?


Solution

  • It kind of sounds like you're expecting NSRange to be like a Python range object. It's not; NSRange is simply a struct

    typedef struct _NSRange {
           NSUInteger location;
           NSUInteger length;
    } NSRange;
    

    not an object. Once you've created one, you can use its members in a plain old for loop:

    NSUInteger year;
    for(year = years.location; year < NSMaxRange(years); year++ ){
        // Do your thing.
    }
    

    (Still working on the assumption that you're thinking about Python.) There's syntax in ObjC called fast enumeration for iterating over the contents of an NSArray that is pleasantly similar to a Python for loop, but since literal and primitive numbers can't be put into an NSArray, you can't go directly from an NSRange to a Cocoa array.

    A category could make that easier, though:

    @implementation NSArray (WSSRangeArray)
    
    + (id)WSSArrayWithNumbersInRange:(NSRange)range
    {
        NSMutableArray * arr = [NSMutableArray array];
        NSUInteger i;
        for( i = range.location; i < NSMaxRange(range); i++ ){
            [arr addObject:[NSNumber numberWithUnsignedInteger:i]];
        }
    
        return arr;
    }
    

    Then you can create an array and use fast enumeration:

    NSArray * years = [NSArray WSSArrayWithNumbersInRange:NSMakeRange(2011, 5)];
    for( NSNumber * yearNum in years ){
        NSUInteger year = [yearNum unsignedIntegerValue];
        // and so on...
    }