问题
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