Question

I have the following string in an NSTextView:

Horus avenged his father Osiris

There are two tags assigned to this, Horus and Osiris. I use NSScanner to scan the string for both tags and highlight them with a yellow background when found.

The code is:

for (Tag *aTag in tags) {
    NSString *aTagName = [aTag name];
    NSUInteger strLength = [aTagName length];
    NSScanner *aScanner = [[NSScanner alloc] initWithString: aString];
    [aScanner setCaseSensitive: YES];
    [aScanner setScanLocation: 0];
    BOOL result = [aScanner scanUpToString: aTagName intoString: nil];
    while (![aScanner isAtEnd]) {
        NSUInteger position = [aScanner scanLocation];
        if (result) {
            NSRange aRange = NSMakeRange(position, strLength);
            [storage removeAttribute: NSBackgroundColorAttributeName range: aRange];
            if (onOrOff) {
                [storage addAttribute: NSBackgroundColorAttributeName value: aColor range: aRange];
            }
            position = position + [aTagName length];
            [aScanner setScanLocation: position];
        }
        [aScanner scanUpToString: aTagName intoString: nil];
    }
}

This fails when the frist tag (in the above example it's Horus) is located at the very beginning (location = 0) of the scanned string. The tag is not found and the code keeps looping.

However, when I replace the string with:

After 10 years Horus avenged his father Osiris

... it all works and both my tags are found (as expected) and nicely highlighted.

Am I missing something or is this a bug in NSScanner?

Was it helpful?

Solution

See the docs for

- (BOOL)scanUpToString:(NSString *)stopString intoString:(NSString **)stringValue

If stopString is the first string in the receiver, then the method returns NO and stringValue is not changed.

The scanner has found the string, but returned NO, because it has not scanned through any characters to do so. Your code then doesn't increase the position variable, because that part is within the if (result) block.

I think removing the if statement should fix the problem. If the scanner didn't find the stopString, the while condition will fail and the code won't get into the loop at all.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top