Looping using NSRange

∥☆過路亽.° 提交于 2019-12-28 04:20:13

问题


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?


回答1:


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...
}



回答2:


Remember that a NSRange is a structure holding two integers, representing the start and length of the range. You can easily loop over all of the contained integers using a for loop.

NSRange years = NSMakeRange(2011, 5);
NSUInteger year;
for(year = years.location; year < years.location + years.length; ++year) {
    // Use the year variable here
}



回答3:


This is a bit of an old question, but an alternative to using an NSArray would be to create an NSIndexSet with the desired range (using indexWithIndexesInRange: or initWithIndexesInRange:) and then using block enumeration as in https://stackoverflow.com/a/4209289/138772. (Seemed relevant as I was just checking on this myself.)




回答4:


My alternate solution for this, was to define a macro just to make shorthand quicker.

#define NSRangeEnumerate(i, range)    for(i = range.location; i < NSMaxRange(range); ++i)

To call it you do:

NSArray *array = @[]; // must contain at least the following range...
NSRange range = NSMakeRange(2011, 5);
NSUInteger i;
NSRangeEnumerate(i, range) {
    id item = array[i];
    // do your thing
}

personally I am still trying to figure out how I can write the macro so I can just call it like:

NSRangeEnumerate(NSUInteger i, range) {

}

which is not supported just yet... hope that helps or makes typing your program quicker



来源:https://stackoverflow.com/questions/8320987/looping-using-nsrange

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!