Cocoa Programming for Mac OS X - Aaron Hillegass [16]
for ( i = 0; i < 10; i++) {
NSNumber *numberToPrint = [array objectAtIndex:i];
NSLog(@"The number at index %d is %@", i, numberToPrint);
}
Here, you are printing the contents of the array to the console. NSLog is a function much like the C function printf(); it takes a format string and a comma-separated list of variables to be substituted into the format string. When displaying the string, NSLog prefixes the generated string with the name of the application and a time stamp.
In printf, for example, you would use %x to display an integer in hexadecimal form. With NSLog, we have all the tokens from printf and the token %@ to display an object. The object gets sent the message description, and the string it returns replaces %@ in the string. We will discuss the description method in detail soon.
All the tokens recognized by NSLog() are listed in Table 3.1.
Table 3.1. Possible Tokens in Objective-C Format Strings
* * *
Note
If the @ symbol before the quotes in @ “The number at index %d is %@” looks a little strange, remember that Objective-C is the C language with a couple of extensions. One of the extensions is that strings are instances of the class NSString. In C, strings are just pointers to a buffer of characters that ends in the null character. Both C strings and instances of NSString can be used in the same file. To differentiate between constant C strings and constant NSStrings, you must put @ before the opening quote of a constant NSString.
// C string
char *foo;
// NSString
NSString *bar;
foo = "this is a C string";
bar = @"this is an NSString";
You will use mostly NSString in Cocoa programming. Wherever a string is needed, the classes in the frameworks expect an NSString. However, if you already have a bunch of C functions that expect C strings, you will find yourself using char * frequently.
You can convert between C strings and NSStrings:
const char *foo = "Blah blah";
NSString *bar;
// Create an NSString from a C string
bar = [NSString stringWithUTF8String:foo];
// Create a C string from an NSString
foo = [bar UTF8String];
Because NSString can hold Unicode strings, you will need to deal with the multibyte characters correctly in your C strings, and this can be quite difficult and time consuming. (Besides the multibyte problem, you will have to wrestle with the fact that some languages read from right to left.) Whenever possible, you should use NSString instead of C strings.
* * *
Our main() function ends by returning 0, indiciating that no error occurred:
return 0;
}
Run the completed command-line tool (Figure 3.3). (If your console doesn’t appear, use the View -> Show Debug Area menu item and ensure that the console, the right half, is enabled.)
Figure 3.3. Completed Execution
Sending Messages to nil
In most object-oriented languages, your program will crash if you send a message to null. In applications written in those languages, you will see many checks for null before sending a message. In Java, for example, you frequently see the following:
if (foo != null) {
foo.doThatThingYouDo();
}
In Objective-C, it is okay to send a message to nil. The message is simply discarded, which eliminates the need for these sorts of checks. For example, this code will build and run without an error:
id foo;
foo = nil;
int bar = [foo count];
This approach is different from how most languages work, but you will get used to it.
You may find yourself asking over and over, “Argg! Why isn’t this method getting called?” Chances are that the pointer you are using, convinced that it is not nil, is in fact nil.
In the preceding example, what is bar set to? Zero. If bar were a pointer, it would be set to nil (zero for pointers). For other types, the value is less predictable.
NSObject, NSArray, NSMutableArray, and NSString
You have now used these standard Cocoa objects: NSObject, NSMutableArray, and NSString. (All classes that come with Cocoa have names with