NSRange: range.location != NSNotFound vs. range.length > 0
Asked Answered
W

3

16

I'm going through some older code in one of my apps and fixing up the code in areas that could be potentially problematic.

I'm seeing a lot of old code using...

NSRange range = //determine range here....
if(range.length > 0)
{
    //do stuff
}

Is that code "fine", or should I change it to this?

NSRange range = //determine range here....
if(range.location != NSNotFound)
{
    //do stuff
}

Are these two methods identical, essentially, or not?

Wristband answered 10/10, 2012 at 20:30 Comment(0)
M
13

The two checks are not always identical. It depends on how the range was generated. Example:

NSRegularExpression *re = [NSRegularExpression
    regularExpressionWithPattern:@"(?= )" options:0 error:NULL];
NSTextCheckingResult *result = [re firstMatchInString:@"hello world"
    options:0 range:NSMakeRange(0, 11)];
NSLog(@"range = %@", NSStringFromRange(result.range));

The range's length is 0, but its location is 5, not NSNotFound.

Masaccio answered 10/10, 2012 at 20:47 Comment(2)
Interesting counter example to the theory that checking for location equalling NSNotFound and length > 0 are essentially the same...Wristband
For a reference here what the documentation has to say for NSRegularExpressions: If the result returned is non-nil, then [result range] will always be a valid range, so it is not necessary to compare it against {NSNotFound, 0}. However, for some regular expressions (though not the example pattern) some capture groups may or may not participate in a given match. If a given capture group does not participate in a given match, then [result rangeAtIndex:idx] will return {NSNotFound, 0}.Fredella
F
6

The answer depends on the function/method you are using. NSRange is just a struct so you need to read the documentation for the function/method you are calling.

Examples:

NSRangeFromString
Returns a range from a textual representation.

... If aString does not contain any integers, this function returns an NSRange struct whose location and length values are both 0.

In this case checking for NSNotFound would not work.


-[NSString rangeOfString:]

... Returns {NSNotFound, 0} if aString is not found or is empty (@"").

Here it is documented that location will be NSNotFound and the length will be 0 so either of the checks would work, however, I would recommend checking the location against NSNotFound.

Fredella answered 10/10, 2012 at 20:49 Comment(2)
So it sounds like what really matters in my question is how the range is determined and what I'm trying to do with the range.Wristband
Yes, read the documentation to determine what you need to check for.Fredella
D
0

NSNotFound is defined as "NSIntegerMax". Even if they produce the same result your second display is far more readable and self documenting. Maybe you shouldn't find them all and change them but just switch to that moving forward.

Discommend answered 10/10, 2012 at 20:34 Comment(2)
So in implementation, they are identical, but the preferred usage is checking if range.location equals NSNotFound or not?Wristband
I feel we are now just talking about style since I believe both will give you the same result. I would just think that if you read the second one it flows and makes sense "the location of the range is found or not found" as opposed to the first which requires interpretation. Either way its pretty minor and you may just pick one convention for the entire file for consistency sake.Discommend

© 2022 - 2024 — McMap. All rights reserved.