NSString and Friends
NSNotFound is a constant integer indicating that some requested element was not found. For example, if you ask for the index of a certain object in an NSArray and the object isn’t present in the array, the result is NSNotFound.
An NSString can be searched using various rangeOf... methods, which return an NSRange. In addition, NSScanner lets you walk through a string looking for pieces that fit certain criteria; for example, with NSScanner (and NSCharacterSet) you can skip past everything in a string that precedes a number and then extract the number. Starting with iOS 3.2, the rangeOfString: family of search methods can specify an option NSRegularExpressionSearch, which lets you search using a regular expression; in iOS 4, regular expressions are fully supported as a separate class, NSRegularExpression (which uses NSTextCheckingResult to describe match results).
In this example from one of my apps, the user has tapped a button whose title is something like “5 by 4” or “4 by 3”. I want to know both numbers; one tells me how many rows the layout is to have, the other how many columns. I use an NSScanner to locate the two numbers:
NSString* s = [as buttonTitleAtIndex:ix];
NSScanner* sc = [NSScanner scannerWithString:s];
int rows, cols;
[sc scanInt:&rows];
[sc scanUpToCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet]
intoString:nil];
[sc scanInt:&cols];
If I were writing this same code to run only on iOS 4, I might do the same thing using a regular expression:
NSString* s = [as buttonTitleAtIndex:ix];
int rowcol[2]; int* prowcol = rowcol;
NSError* err = nil;
NSRegularExpression* r = [NSRegularExpression regularExpressionWithPattern:@"\\d"
options:0
error:&err];
// error-checking omitted
for (NSTextCheckingResult* match in [r matchesInString:s
options:0
range:NSMakeRange(0, [s length])])
*prowcol++ = [[s substringWithRange: [match range]] intValue];
The syntax seems oddly tortured, though, because we must convert each match from an NSTextCheckingResult to a range, then to a substring of our original string, and finally to an integer.
String drawing in a graphical context can be performed simply with methods provided through the UIStringDrawing category on NSString.
NSDate and Friends
An NSDate is a date and time, represented internally as a number of seconds (NSTimeInterval) since some reference date. Calling [NSDate date] gives you a date object for the current date and time; other date operations may involve NSDateComponents and NSCalendar and can be a bit tricky because calendars are complicated (see the Date and Time Programming Guide).
You will also likely be concerned with dates represented as strings. Creation and parsing of date strings involves NSDateFormatter, which uses a format string similar to NSString’s stringWithFormat. A complication is added by the fact that the exact string representation of a date component or format can depend upon the user’s locale, consisting of language, region format, and calendar settings. (Actually, locale considerations can also play a role in NSString format strings.)
In this example from one of my apps, I prepare the content of a UILabel reporting the date and time when our data was last updated. The app is not localized — the word “at” appearing in the string is always going to be in English — so I want complete control of the presentation of the date and time components as well. To get it, I have to insist upon a particular locale:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
if ([[NSLocale availableLocaleIdentifiers] indexOfObject:@"en_US"] != NSNotFound) {
NSLocale* loc = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
[df setLocale:loc]; // force English month name and time zone name if possible
}
[df setDateFormat:@"d MMMM yyyy 'at' h:mm a z"];
NSString* lastUpdated = [df stringFromDate: [NSDate date]];
NSNumber
An NSNumber is an object that wraps a numeric value (including BOOL).
NSValue
NSValue is NSNumber’s superclass. Use it for wrapping nonnumeric C values such as structs. Convenience methods provided by through the NSValueUIGeometryExtensions category on NSValue (see the NSValue UIKit Additions Reference) allow easy wrapping and unwrapping of CGPoint, CGSize, CGRect, CGAffineTransform, and UIEdgeInsets; additional categories allow easy wrapping and unwrapping of CATransform3D, CMTime, CMTimeMapping, and CMTimeRange.You are unlikely to need to store any other kind of C value in an NSValue, but you can if you need to.
NSData
NSData is a general sequence of bytes. It is immutable; the mutable version is its subclass NSMutableData.
In practice, NSData tends to arise in two main ways:
1)When downloading data from the Internet. For example, the NSURLConnection class supplies whatever it retrieves from the Internet as NSData. Transforming it from there into (let’s say) a string, specifying the correct encoding, would then be up to you.
2)When storing an object as a file or in user preferences. For example, you can’t store a UIColor value directly into user preferences. So if the user has made a color choice and you need to save it, you transform the UIColor into an NSData (using NSKeyedArchiver) and save that:
[[NSUserDefaults standardUserDefaults] registerDefaults:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSKeyedArchiver archivedDataWithRootObject:[UIColor blueColor]],
@"myColor",
nil]];