Why Are There Two Nsnotfound

What is the availability of NSNotFound?

Insert availabilityOfNSNotFound == NSNotFound joke here.


At some point when Apple was pushing mandatory 64-bit device support (iOS 8.4 SDK?), the declaration of NSNotFound was changed from:

enum {NSNotFound = NSIntegerMax};

to

static const NSInteger NSNotFound = NSIntegerMax;

You can verify this in <Foundation/NSObjCRuntime.h>.

The documentation was never changed, so the availability of the enum NSNotFound is no longer in the SDK. But as of iOS 9 and above, the static const NSInteger NSNotFound is available.

Although I cannot answer the true availability of NSNotFound since I don't work for Apple (as a developer I think it's safe to use in all iOS versions since 2.0, or else a lot of Foundation classes would break since they can return NSNotFound), you can check to see if the memory location for NSNotFound is NULL:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"
BOOL found = (&NSNotFound != NULL);
#pragma clang diagnostic pop
if (found) {
NSLog(@"meh");
}

Should I compare NSNotFound to NSInteger or NSUInteger?

You should use NSUInteger

The reason behind this is "The array index is not going to minus (i.e object at index -5)"

typedef int NSInteger;
typedef unsigned int NSUInteger;

NSInteger must be used when there are probability to get values in plus or minus.

Hope it helps.
Thanks

Why does range.location == NSNotFound mean that a word is found and not the opposite?

If I understand it correctly, that function returns true if the given word does not contain a misspelled word, so

return misspelledRange.location == NSNotFound;

makes sense.

NSNotFound not working with NSUser default

Obviously there is a misunderstanding: NSNotFound is not equal to key is missing, it's a valid integer value.

The easiest way to keep your logic is to register the key-value pair with NSNotFound as the default value.

As soon as possible (applicationDidFinishLaunching or earlier) write

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *defaultValues = @{@"selectedUnit": @(NSNotFound)};
[defaults registerDefaults:defaultValues];

That means NSNotFound is considered as default value until it's overwritten the first time. The 3 lines must be executed every time the application launches. If the app is reinstalled the default value is taken again.

Now you can use your logic in the question.

PS: You don't need to synchronize after writing. The framework does that periodically.

NSRange not matching with NSNotFound

Looking at your logic, sender.currentTitle is always going to be @"." in your else statement, and so your range is always going to have a location of 0.

NSNotFound for Swift

It's simply aggregate initialization syntax for structs in C. You can use the NSRange initializer instead:

let notFoundRange = NSRange(location: NSNotFound, length: 0)

Or, perhaps more simply:

if linkRange.location != NSNotFound { ...

NSRange: range.location != NSNotFound vs. range.length 0

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.

What happens when rangeOfCharacterFromSet is called?

- (void)test {
NSString *str = @"input content";
NSCharacterSet *characterSet = [NSCharacterSet decimalDigitCharacterSet];
NSRange range = [str rangeOfCharacterFromSet:characterSet];
NSLog(@"location:%ld, length:%ld", range.location, range.length);
// range.location is 9223372036854775807, in fact it is a NSNotFound which means not exists, range.length is 0

str = @"input 1";
range = [str rangeOfCharacterFromSet:characterSet];
NSLog(@"location:%ld, length:%ld", range.location, range.length);
// range.location is 6, range.length is 1

str = @"input 123";
range = [str rangeOfCharacterFromSet:characterSet];
NSLog(@"location:%ld, length:%ld", range.location, range.length);
// range.location is 6, range.length is 1

str = @"123 input 123";
range = [str rangeOfCharacterFromSet:characterSet];
NSLog(@"location:%ld, length:%ld", range.location, range.length);
// range.location is 0, range.length is 1
}

In the test, str is the receiver, when you call a method, who call who is reciever: [receiver callTheMethod]. Abount NSCharacterSet, I think the document explains clearly:

An NSCharacterSet object represents a set of Unicode-compliant characters. NSString and NSScanner objects use NSCharacterSet objects to group characters together for searching operations, so that they can find any of a particular set of characters during a search. The cluster’s two public classes, NSCharacterSet and NSMutableCharacterSet, declare the programmatic interface for static and dynamic character sets, respectively.

NSRange is the result of [str rangeOfCharacterFromSet:characterSet], it is a struct, range.location is the first index in str which is included in characterSet, it is a NSInteger type, when the str not exits a the content of characterSet it will be a very big integer, and it means NSNotFound. range.length means as the words, at here, it always is 1 unless range.location is NSNotFound.

Hope it helps.



Related Topics



Leave a reply



Submit