Hello NSScanner

In an attempt to broaden my iOS development horizons, I thought I would take a look at some of those iOS classes and components that you may not know too much about or have used in the past, but probably should due to their elegance or functionality.

Today’s example is NSScanner (reference and programming guide). This handy class has one main purpose, to scan through a source string into either strings or other data types, such as integers and floats.

Converting a NSString to an integer is fairly trivial, as you can just do something like [myString intValue]. However, the NSScanner class maintains a pointer as the source string is scanned, so if you need to loop through a string and scan multiple values in from one string, NSScanner is your class. One other interesting thing that NSScanner can do is to take in a string of hexadecimal digits and convert them as well.

In the simplest case, here is how you would convert a string to an integer:

NSString *theString = @"42";
unsigned int theValue;
[[NSScanner scannerWithString:theString] scanHexInt:&theValue];

All of the scan methods return a BOOL that lets you know if the scan was successful or not, so be sure to not do what I am doing above and check the return value to make sure there was not an error.

Here is how you would process a hexadecimal string and examine each byte in the string:

int theLength = [hexString length];
for (int i = 0; i < theLength; i += 2)
{
    NSRange theRange = NSMakeRange(i, 2);
    NSString *hexDigits = [hexString substringWithRange:theRange];
    unsigned int theValue;
    [[NSScanner scannerWithString:hexDigits] scanHexInt:&theValue];
    NSLog(@"Byte number %d is %d\n", (i / 2), theValue);
}

And a final example, let’s say you had the text of an HTML page and you wanted to pull out all of the links in the page (denoted by an A tag with an HREF= entry). Here is some code that would do that:

NSScanner *scanner = [NSScanner scannerWithString:theHTMLString];
NSString *foundString = nil;
[scanner scanUpToString:@"a href=" intoString:nil];
while (![scanner isAtEnd])
{
    [scanner scanUpToString:@"\"" intoString:nil];
    scanner.scanLocation++;
    [scanner scanUpToString:@"\"" intoString:&foundString];
    [scanner scanUpToString:@"a href=" intoString:nil];
    NSLog(@"Link found: %@", foundString);
}

If you would like to download the NSScannerTest project that I put together to demonstrate these features in a running app, here is the download link, make sure to be using the latest version of Xcode and iOS SDK:

NSScannerTest source code

(Bonus mini tutorial: If you download and look at the source code, you will get a little sampling of NSRegularExpression and NSTextCheckingResult, two Foundation classes that probably deserve a tutorial posting of their own in the future.)

I have a couple of ideas on what I am going to cover next, but if you have any suggestions, please use the comments. Thanks and I’ll see you next time.

Leave a Reply