Chapter 6. Essential Cocoa Paradigms

In this chapter you will explore a handful of programming topics that represent the fundamental building blocks of a Cocoa application. First, you’ll learn how to use Cocoa’s collection classes, a set of objects whose purpose is to hold other objects. Next, you’ll explore the basics of building graphical user interfaces in Cocoa. You’ll learn to use Interface Builder and discover how this powerful tool interacts with Project Builder and the Cocoa frameworks to allow you to very quickly prototype and build applications. Last, you’ll delve into the intricacies of object ownership and disposal in Cocoa, ensuring that your applications use resources efficiently.

These topics have been singled out for special attention because they are central to the design of the Cocoa frameworks, and the architectural perspectives involved are likely to be unfamiliar to developers new to the subtleties of object-oriented programming. Exploring these design patterns will help steep you in the mindset of Cocoa’s creators, as well as illustrate some of the powerful design approaches available with a language as dynamic as Objective-C. Understanding the principles involved will help you use the Cocoa tools and frameworks more effectively, providing the experience you need to work with them instead of against them.

Cocoa’s Collection Classes

Several classes in Cocoa’s Foundation framework create objects whose purpose is to hold other objects (literally, references to objects); these classes are called collection classes. The two most commonly used collection classes are NSArray and NSDictionary. NSArray stores and retrieves objects in an ordered fashion through zero-based indexing. Dictionaries store and retrieve objects using key-value pairs. These collection classes, shown in Figure 6.1, are extremely useful in Cocoa application development.

Cocoa collection classes

Figure 6-1. Cocoa collection classes

Collection classes come in two forms, mutable and immutable. The immutable versions of these classes (NSArray and NSDictionary, for example) allow you to add items when the collection is created but no further changes are allowed. The mutable versions (NSMutableArray, NSMutableDictionary) allow you to add and remove objects programmatically after the collection object is created.

All collection objects enable you to access a contained value that satisfies a particular external property. This property, generally referred to as a key, varies according to the organizing scheme enforced by the type of collection. For example, the key for an array is an integer that specifies position within the collection; however, a dictionary—for which the term key has more of a conventional meaning—permits any arbitrary value to act as the key for retrieving a contained value.

In addition to storage and retrieval using keys, much of the power of collection classes lies in their ability to manipulate the objects they contain. The collection classes implement methods for performing a variety of functions on the objects they contain. Not every collection object can perform every function, but in general, collection objects can:

  • Derive their initial contents from files and URLs as well as other collections of objects

  • Add, remove, locate, and sort their contents

  • Compare their contents with other collection objects

  • Enumerate over their contents

  • Send a message to their contents

  • Store their contents to a file on disk and later retrieve it (with the help of NSArchiver/NSUnarchiver)

Because you will use collection objects frequently when building Cocoa applications, it’s important to get a basic feel for how they work. Exploring the collection classes will also provide an opportunity to exercise your Objective-C and Project Builder skills.

Working with NSArray

In this section you will modify the Hello World application from Chapter 5, so that it instantiates and exercises an instance of the NSMutableArray class:

  1. Open the Hello World project if it is not already open.

  2. Open main.m and add a declaration for an NSMutableArray just after the declaration of the autorelease pool and before the call to NSLog:

    NSMutableArray *myArray;
  3. Add the code to create a new array:

    myArray = [[NSMutableArray alloc] init];
  4. Add code to print the contents of the array object. In this call to NSLog, the %@ is replaced by the object. The %@ works exactly as it would in a printf call; %@ is the escape for an object value, in this case, an NSString. Note that NSLog automatically sends the description message to the array so that information about the array’s contents will be printed:

    NSLog(@"Array description: %@ items.
    ", myArray);
  5. Add code to release the array. This statement tells the runtime that we are finished with the array so it can be safely deallocated:

    [myArray release];

Your main function should look exactly like that in Example 6.1.

Example 6-1. Creating a Mutable Array

int main (int argc, const char *argv[]) 
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSMutableArray *myArray;

    NSLog(@"Hello World: This is a Foundation Tool.
");

    myArray = [[NSMutableArray alloc] init];

    NSLog(@"Array description: %@ items.
", myArray);

    [myArray release];
    [pool release];
    return 0;
}

Build and run the application. You should see a new string in the Run pane similar to this:

Nov 10 15:56:12 HelloWorld[256] Array description: () items.

Right now, the array is empty, but when you add items, their descriptions will appear between the parentheses.

Spend a few minutes playing with NSMutableArray. Here are some suggestions:

  • Add a string. Note that arrays retain but do not copy their member objects. See Section 6.4.1.10 later in this chapter for more information.

    [myArray addObject: @"Here's a string!"];
  • Find out how many items are in the array:

    int itemCount;
    itemCount = [myArray count];
  • Get an object from the array:

    NSString *myString;
    myString = [myArray objectAtIndex: 0];
  • Insert an object:

    [myArray insertObject: @"Hello2" atIndex: 0];
  • Swap items:

    [myArray exchangeObjectAtIndex: 0 withObjectAtIndex: 1];

Consult the class specifications for NSArray and NSMutableArray in /Developer/Documentation/Cocoa for comprehensive documentation on all of the methods for this container class.

Working with NSDictionary

A dictionary—an object of the NSDictionary or NSMutableDictionary class—is a hashing-based collection whose keys for accessing its values are arbitrary, program-defined pieces of data. Although the key is usually a string (an NSString object), it can be any object—with certain caveats: the object used as a key must conform to the NSCopying protocol and respond to the isEqual: message). The keys of dictionaries are unlike the keys of the other collection objects in that, conceptually, they are also contained by the collection along with the values. Dictionaries are primarily useful for holding and organizing data that can be labeled, such as values extracted from text fields in the user interface.

In Cocoa, a dictionary differs from an array in that the key used to access a particular value in the dictionary remains the same as values are added to or removed from the dictionary—until a value associated with a particular key is replaced or removed. In an array, the key (the index) that is used to retrieve a particular value can change over time as values are inserted into or deleted from the array. Also, unlike an array, a dictionary does not put its values in any order. To enable later retrieval of a value, the key of the key-value pair should be constant (or be treated as constant); if the key changes after being used to put a value in the dictionary, the value might not be retrievable. The keys of a dictionary form a set; in other words, keys are guaranteed to be unique in a dictionary.

Working with dictionaries

In this section you will again modify the Hello World application so that it instantiates and exercises an instance of the NSMutableDictionary class:

  1. Open the Hello World project if it is not already open, and bring up main.m for editing.

  2. Add a declaration for a local variable of type NSMutableDictionary:

    NSMutableDictionary *myDict;
  3. Add the code to create a new dictionary:

    myDict = [[NSMutableDictionary alloc] init];
  4. Add code to print the contents of the dictionary object:

    NSLog(@"Dict description: %@ items.
    ", myDict);
  5. Add code to release the dictionary:

    [myDict release];

Spend a few minutes playing with NSMutableDictionary. Here are some suggestions:

  • Add a key-value pair:

    [myDict setObject:@"stringOne" forKey:@"keyOne"];
  • Get an object from the dictionary using its key:

    myString = [myDict objectForKey:@"keyOne"];
  • Add several different key-value pairs to the dictionary and then get an array of all the keys. Use a loop to print them all out:

    keyArray = [myDict allKeys];
    for (index = 0; index < [keyArray count]; index++)
        NSLog(@"Dictionary key at index %i is: %@.
    ", index, 
            [keyArray objectAtIndex: index]);

Consult the class specifications for NSDictionary and NSMutableDictionary for comprehensive documentation on all methods for this container class.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.212.238