Programming in Objective-C 2.0 edition phần 7 potx

59 341 0
Programming in Objective-C 2.0 edition phần 7 potx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

345 Array Objects lower-level array constructs provided by the language might be more efficient, in terms of both memory usage and execution speed. Refer to the section titled “Arrays” in Chapter 13 for more information. Making an Address Book Let’s take a look at an example that starts to combine a lot of what you’ve learned to this point by creating an address book. 2 Your address book will contain address cards. For the sake of simplicity, your address cards will contain only a person’s name and email address. Extend this concept to other information, such as address and phone number, is straight- forward, but we leave that as an exercise for you at the end of this chapter. Creating an Address Card We start by defining a new class called AddressCard.You’ll want the capability to create a new address card, set its name and email fields, retrieve those fields, and print the card. In a graphics environment, you could use some nice routines such as those provided by the Application Kit framework to draw your card onscreen. But here you stick to a simple Console interface to display your address cards. Program 15.8 shows the interface file for your new AddressCard class.We’re not go- ing to synthesize the accessor methods yet; writing them yourself offers valuable lessons. Program 15.8 Interface File AddressCard.h #import <Foundation/NSObject.h> #import <Foundation/NSString.h> @interface AddressCard: NSObject { NSString *name; NSString *email; } -(void) setName: (NSString *) theName; -(void) setEmail: (NSString *) theEmail; -(NSString *) name; -(NSString *) email; -(void) print; @end 2 Mac OS X provides an entire Address Book framework, which offers extremely powerful capabilities for working with address books. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 346 Chapter 15 Numbers, Strings, and Collections This is straightforward, as is the implementation file in Program 15.8. Program 15.8 Implementation File AddressCard.m #import “AddressCard.h” @implementation AddressCard -(void) setName: (NSString *) theName { name = [[NSString alloc] initWithString: theName]; } -(void) setEmail: (NSString *) theEmail { email = [[NSString alloc] initWithString: theEmail]; } -(NSString *) name { return name; } -(NSString *) email { return email; } -(void) print { NSLog (@”====================================”); NSLog (@”| |”); NSLog (@”| %-31s |”, [name UTF8String]); NSLog (@”| %-31s |”, [email UTF8String]); NSLog (@”| |”); NSLog (@”| |”); NSLog (@”| |”); NSLog (@”| O O |”); NSLog (@”====================================”); } @end You could have the setName: and setEmail: methods store the objects directly in their respective instance variables with method definitions like these: -(void) setName: (NSString *) theName { name = theName; } Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 347 Array Objects -(void) setEmail: (NSString *) theEmail { email = theEmail; } But the AddressCard object would not own its member objects.We talked about the motivation for an object to take ownership with respect to the Rectangle class owning its origin object in Chapter 8,“Inheritance.” Defining the two methods in the following way would also be an incorrect approach because the AddressCard methods would still not own their name and email objects— NSString would own them: -(void) setName: (NSString *) theName { name = [NSString stringWithString: theName]; } -(void) setEmail: (NSString *) theEmail { email = [NSString stringWithString: theEmail]; } Returning to Program 15.8, the print method tries to present the user with a nice display of an address card in a format resembling a Rolodex card (remember those?).The %-31s characters to NSLog indicate to display a UTF8 C-string within a field width of 31 characters, left-justified.This ensures that the right edges of your address card line up in the output. It’s used in this example strictly for cosmetic reasons. With your AddressCard class in hand, you can write a test program to create an address card, set its values, and display it (see Program 15.8). Program 15.8 Test Program #import “AddressCard.h” #import <Foundation/NSAutoreleasePool.h> int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString *aName = @”Julia Kochan”; NSString *aEmail = @”jewls337@axlc.com”; AddressCard *card1 = [[AddressCard alloc] init]; Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 348 Chapter 15 Numbers, Strings, and Collections [card1 setName: aName]; [card1 setEmail: aEmail]; [card1 print]; [card1 release]; [pool drain]; return 0; } Program 15.8 Output ===================================== | | | Julia Kochan | | jewls337@axlc.com | | | | | | | | O O | ===================================== In this program, the line [card1 release]; is used to release the memory your address card uses.You should realize from previous discussions that releasing an AddressCard object this way does not also release the mem- ory you allocated for its name and email members.To make the AddressCard leak free, you need to override the dealloc method to release these members whenever the mem- ory for an AddressCard object is released. This is the dealloc method for your AddressCard class: -(void) dealloc { [name release]; [email release]; [super dealloc]; } The dealloc method must release its own instance variables before using super to destroy the object itself.That’s because an object is no longer valid after it has been deallocated. To make your AddressCard leak free, you must also modify your setName: and setEmail: methods to release the memory used by the objects stored in their respective instance variables. If someone changes the name on a card, you need to release the memory that the old name takes up before you replace it with the new one. Similarly, Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 349 Synthesized AddressCard Methods for the email address, you must release the memory it uses before you replace it with the new one. These are the new setName: and setEmail: methods that ensure that we have a class that handles memory management properly: -(void) setName: (NSString *) theName { [name release]; name = [[NSString alloc] initWithString: theName]; } -(void) setEmail: (NSString *) theEmail { [email release]; email = [[NSString alloc] initWithString: theEmail]; } You can send a message to a nil object; therefore, the message expressions [name release]; and [email release]; are okay even if name or email have not been previously set. Synthesized AddressCard Methods Now that we’ve discussed the correct way to write the accessor methods setName: and setEmail:, and you understand the important principles, we can go back and let the sys- tem generate the accessor methods for you. Consider the second version of the AddressCard interface file: #import <Foundation/NSObject.h> #import <Foundation/NSString.h> @interface AddressCard: NSObject { NSString *name; NSString *email; } @property (copy, nonatomic) NSString *name, *email; -(void) print; @end The line @property (copy, nonatomic) NSString *name, *email; Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 350 Chapter 15 Numbers, Strings, and Collections lists the attributes copy and nonatomic for the properties.The copy attribute says to make a copy of the instance variable in its setter method, as you did in the version you wrote. The default action is not to make a copy, but to instead perform a simple assignment (that’s the default attribute assign), an incorrect approach that we recently discussed. The nonatomic attribute specifies that the getter method should not retain or autorelease the instance variable before returning its value. Chapter 18 discusses this topic in greater detail. Program 15.9 is the new AddressCard implementation file that specifies that the acces- sor methods be synthesized. Program 15.9 Implementation File AddressCard.m with Synthesized Methods #import “AddressCard.h” @implementation AddressCard @synthesize name, email; -(void) print { NSLog (@”====================================”); NSLog (@”| |”); NSLog (@”| %-31s |”, [name UTF8String]); NSLog (@”| %-31s |”, [email UTF8String]); NSLog (@”| |”); NSLog (@”| |”); NSLog (@”| |”); NSLog (@”| O O |”); NSLog (@”====================================”); } @end We leave it as an exercise to you to verify that the new AddressCard definition with its synthesized accessor methods works with the test program shown in Program 15.9. Now let’s add another method to your AddressCard class.You might want to set both the name and email fields of your card with one call.To do so, add a new method, setName:andEmail:. 3 The new method looks like this: -(void) setName: (NSString *) theName andEmail: (NSString *) theEmail { self.name = theName; self.email = theEmail; } 3 You also might want an initWithName:andEmail: initialization method, but we don’t show that here. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 351 Synthesized AddressCard Methods By relying on the synthesized setter methods to set the appropriate instance variables (instead of setting them directly inside the method yourself), you add a level of abstraction and, therefore, make the program slightly more independent of its internal data structures. You also take advantage of the synthesized method’s properties, which in this case, copy instead of assign the value to the instance variable. Program 15.9 tests your new method. Program 15.9 Test Program #import <Foundation/Foundation.h> #import “AddressCard.h” int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString *aName = @”Julia Kochan”; NSString *aEmail = @”jewls337@axlc.com”; NSString *bName = @”Tony Iannino”; NSString *bEmail = @”tony.iannino@techfitness.com”; AddressCard *card1 = [[AddressCard alloc] init]; AddressCard *card2 = [[AddressCard alloc] init]; [card1 setName: aName andEmail: aEmail]; [card2 setName: bName andEmail: bEmail]; [card1 print]; [card2 print]; [card1 release]; [card2 release]; [pool drain]; return 0; } Program 15.9 Output ==================================== | | | Julia Kochan | | jewls337@axlc.com | | | | | | | | O O | ==================================== Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 352 Chapter 15 Numbers, Strings, and Collections ==================================== | | | Tony Iannino | | tony.iannino@techfitness.com | | | | | | | | O O | ==================================== Your AddressCard class seems to be working okay.What if you wanted to work with a lot of AddressCards? It would make sense to collect them together, which is exactly what you’ll do by defining a new class called AddressBook.The AddressBook class will store the name of an address book and a collection of AddressCards, which you’ll store in an array object.To start, you’ll want the ability to create a new address book, add new address cards to it, find out how many entries are in it, and list its contents. Later, you’ll want to be able to search the address book, remove entries, possibly edit existing entries, sort it, or even make a copy of its contents. Let’s get started with a simple interface file (see Program 15.10). Program 15.10 Addressbook.h Interface File #import <Foundation/NSArray.h> #import “AddressCard.h” @interface AddressBook: NSObject { NSString *bookName; NSMutableArray *book; } -(id) initWithName: (NSString *) name; -(void) addCard: (AddressCard *) theCard; -(int) entries; -(void) list; -(void) dealloc; @end The initWithName: method sets up the initial array to hold the address cards and store the name of the book, whereas the addCard: method adds an AddressCard to the book.The entries method reports the number of address cards in your book, and the list method gives a concise listing of its entire contents. Program 15.10 shows the im- plementation file for your AddressBook class. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 353 Synthesized AddressCard Methods Program 15.10 Addressbook.m Implementation File #import “AddressBook.h” @implementation AddressBook; // set up the AddressBook’s name and an empty book -(id) initWithName: (NSString *) name { self = [super init]; if (self) { bookName = [ NSString alloc] initWithString: name]; book = [[NSMutableArray alloc] init]; } return self; } -(void) addCard: (AddressCard *) theCard { [book addObject: theCard]; } -(int) entries { return [book count]; } -(void) list { NSLog (@”======== Contents of: %@ =========”, bookName); for ( AddressCard *theCard in book ) NSLog (@”%-20s %-32s”, [theCard.name UTF8String], [theCard.email UTF8String]); NSLog (@”==================================================”); } -(void) dealloc { [bookName release]; [book release]; [super dealloc]; } @end Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 354 Chapter 15 Numbers, Strings, and Collections The initWithName: method first calls the init method for the superclass to perform its initialization. Next, it creates a string object (using alloc so it owns it) and sets it to the name of the address book passed in as name.This is followed by the allocation and ini- tialization of an empty mutable array that is stored in the instance variable book. You defined initWithName: to return an id object, instead of an AddressBook one. If AddressBook is subclassed, the argument to initWithName: isn’t an AddressBook object; its type is that of the subclass. For that reason, you define the return type as a generic ob- ject type. Notice also that in initWithName:, you take ownership of the bookName and book in- stance variables by using alloc. For example, if you created the array for book using the NSMutableArray array method, as in book = [NSMutableArray array]; you would still not be the owner of the book array; NSMutableArray would own it.Thus, you wouldn’t be able to release its memory when you freed up the memory for an AddressBook object. The addCard: method takes the AddessCard object given as its argument and adds it to the address book. The count method gives the number of elements in an array.The entries method uses this to return the number of address cards stored in the address book. Fast Enumeration The list method’s for loop shows a construct you haven’t seen before: for ( AddressCard *theCard in book ) NSLog (@”%-20s %-32s”, [theCard.name UTF8String], [theCard.email UTF8String]); This uses a technique known as fast enumeration to sequence through each element of the book array.The syntax is simple enough:You define a variable that will hold each ele- ment in the array in turn ( AddressCard *theCard).You follow that with the keyword in, and then you list the name of the array.When the for loop executes, it assigns the first element in the array to the specified variable and then executes the body of the loop. Then it assigns the second element in the array to the variable and executes the body of the loop.This continues in sequence until all elements of the array have been assigned to the variable and the body of the loop has executed each time. Note that if theCard had been previously defined as an AddressCard object, the for loop would more simply become this: for ( theCard in book ) Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... // Create an integer object #define INTOBJ(v) [NSNumber numberWithInteger: v] // Add a print method to NSSet with the Printing category @interface NSSet (Printing); -(void) print; @end @implementation NSSet (Printing); -(void) print { printf (“{“); for (NSNumber *element in self) printf (“ %li “, (long) [element integerValue]); printf (“}\n”); } @end int main (int argc, char *argv[])... #import “AddressBook.h” #import int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString NSString NSString NSString NSString NSString NSString NSString *aName = @”Julia Kochan”; *aEmail = @”jewls3 37@ axlc.com”; *bName = @”Tony Iannino”; *bEmail = @”tony.iannino@techfitness.com”; *cName = @”Stephen Kochan”; *cEmail = @”steve@kochan-wood.com”;... #import “AddressBook.h” #import int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString NSString NSString NSString NSString NSString NSString NSString *aName = @”Julia Kochan”; *aEmail = @”jewls3 37@ axlc.com”; *bName = @”Tony Iannino”; *bEmail = @”tony.iannino@techfitness.com”; *cName = @”Stephen Kochan”; *cEmail = @”steve@kochan-wood.com”;... #import “AddressBook.h” #import int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString NSString NSString NSString NSString NSString NSString NSString *aName = @”Julia Kochan”; *aEmail = @”jewls3 37@ axlc.com”; *bName = @”Tony Iannino”; *bEmail = @”tony.iannino@techfitness.com”; *cName = @”Stephen Kochan”; *cEmail = @”steve@kochan-wood.com”;... [[NSAutoreleasePool alloc] init]; NSMutableSet *set1 = [NSMutableSet setWithObjects: INTOBJ(1), INTOBJ(3), INTOBJ(5), INTOBJ(10), nil]; NSSet *set2 = [NSSet setWithObjects: INTOBJ(-5), INTOBJ(100), INTOBJ(3), INTOBJ(5), nil]; NSSet *set3 = [NSSet setWithObjects: INTOBJ(12), INTOBJ(200), INTOBJ(3), nil]; 371 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 372 Chapter 15 Numbers, Strings, and... Kochan”; NSString *aEmail = @”jewls3 37@ axlc.com”; NSString *bName = @”Tony Iannino”; NSString *bEmail = @”tony.iannino@techfitness.com”; NSString *cName = @”Stephen Kochan”; NSString *cEmail = @”steve@kochan-wood.com”; NSString *dName = @”Jamie Baker”; NSString *dEmail = @”jbaker@kochan-wood.com”; AddressCard *card1 = [[AddressCard alloc] init]; AddressCard *card2 = [[AddressCard alloc] init]; AddressCard... exists Set Objects A set is a collection of unique objects, and it can be mutable or immutable Operations include searching, adding, and removing members (mutable sets); comparing two sets; and finding the intersection and union of two sets To work with sets in your program, include the following line: #import Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com... unnecessary typing Of course, your print me hod is not tha general because it works only with sets that have integer members in them But it’s a good reminder here of how to add methods to a class through a category.5 (Note that the C library’s printf routine is used in the print method to display the elements of each set on a single line.) setWithObjects: creates a new set from a nil-terminated list of... an NSUInteger integer representing a valid index number into the array; selector is a selector object of type SEL; and size is an NSUInteger integer Table 15.4 Common NSArray Methods Method Description +(id) arrayWithObjects: obj1, obj2, nil Creates a new array with obj1, obj2, as its elements -(BOOL) containsObject: obj Determines whether the array contains obj (uses the isEqual: method) -(NSUInteger)... from mutable set set1 [set1 [set1 NSLog [set1 addObject: INTOBJ(4)]; removeObject: INTOBJ(10)]; (@”set1 after adding 4 and removing 10: “); print]; // get intersection of two sets [set1 intersectSet: set2]; NSLog (@”set1 intersect set2: “); [set1 print]; // union of two sets [set1 unionSet:set3]; NSLog (@”set1 union set3: “); [set1 print]; [pool drain]; return 0; } Simpo PDF Merge and Split Unregistered . with respect to the Rectangle class owning its origin object in Chapter 8,“Inheritance.” Defining the two methods in the following way would also be an incorrect approach because the AddressCard. objects— NSString would own them: -(void) setName: (NSString *) theName { name = [NSString stringWithString: theName]; } -(void) setEmail: (NSString *) theEmail { email = [NSString stringWithString: theEmail]; } Returning. (NSString *) theName { [name release]; name = [[NSString alloc] initWithString: theName]; } -(void) setEmail: (NSString *) theEmail { [email release]; email = [[NSString alloc] initWithString:

Ngày đăng: 12/08/2014, 23:22

Từ khóa liên quan

Mục lục

  • About the Author

  • About the Technical Reviewers

  • We Want to Hear from You!

  • Reader Services

  • Introduction

    • What You Will Learn from This Book

    • How This Book Is Organized

    • Acknowledgments

    • The Objective-C 2.0 Language

      • Programming in Objective-C

        • Compiling and Running Programs

        • Explanation of Your First Program

        • Displaying the Values of Variables

        • Summary

        • Exercises

        • Classes, Objects, and Methods

          • What Is an Object, Anyway?

          • Instances and Methods

          • An Objective-C Class for Working with Fractions

          • The @interface Section

          • The @implementation Section

          • The program Section

          • Accessing Instance Variables and Data Encapsulation

          • Summary

Tài liệu cùng người dùng

Tài liệu liên quan