I think the point of the exercise is to prove ownership of the object(s), this is in contrast to
Chapter 15 Exercise 6 Here's what I did on this one:
// Chapter 15 Exercise 11
// When the addCard: method is used to add an address card to the address book,
// who owns that address card? Can any of the information on that card be later
// changed that would affect the card stored in the address book? Can you think
// of a safer way to implement the addCard: method?
// main.m
#import <Foundation/Foundation.h>
#import "AddressCard.h"
#import "AddressBook.h"
int main (int argc, char * argv[])
{
@autoreleasepool {
NSString *aName = @"Julia Kochan";
NSString *aEmail = @"jewls337@axlc.com";
NSString *bName = @"Tony Iannino";
NSString *bEmail = @"tony.iannino@techfitness.com";
NSString *cName = @"Stephen Kochan";
NSString *cEmail = @"steve@classroomM.com";
NSString *dName = @"Jamie Baker";
NSString *dEmail = @"jbaker@classroomM.com";
NSString *eName = @"Ella Smith";
NSString *eEmail = @"ella.smith@csmithent.com";
NSString *eAddress = @"123 Main Street";
NSString *eCity = @"Anywhere";
NSString *eZip = @"12345";
NSString *eCountry = @"USA";
NSString *ePhone = @"(212) 555-1212";
AddressCard *card1 = [[AddressCard alloc] init];
AddressCard *card2 = [[AddressCard alloc] init];
AddressCard *card3 = [[AddressCard alloc] init];
AddressCard *card4 = [[AddressCard alloc] init];
AddressCard *card5 = [[AddressCard alloc] init];
AddressBook *myBook = [[AddressBook alloc] initWithName: @"Linda’s Address Book"];
// First set up four address cards
[card1 setName: aName andEmail: aEmail];
[card2 setName: bName andEmail: bEmail];
[card3 setName: cName andEmail: cEmail];
[card4 setName: dName andEmail: dEmail];
[card5 setName: eName andEmail: eEmail andAddress: eAddress
andCity: eCity andZip: eZip andCountry: eCountry andPhone: ePhone];
// Add some cards to the address book
[myBook addCard2: card1];
[myBook addCard2: card2];
[myBook addCard2: card3];
[myBook addCard2: card4];
[myBook addCard2: card5];
// List the book
[myBook list];
//change card1
NSLog(@"Julia Kochan card changed from card1\ncard1 info:");
[card1 setName: @"Card1 test" andEmail: @"test" andAddress: @"test" andCity: @"test" andZip: @"test" andCountry: @"test" andPhone: @"test"];
[card1 printAll];
// List the book again to verify Julia wasn't changed in myBook
[myBook list];
// Remove steve from myBook
NSLog (@"remove: steve");
if ([myBook removeName: @"steve"])
NSLog (@"remove successful");
else
NSLog (@"remove unsuccessful");
// List the book to verify Stephen was removed from myBook
[myBook list];
// Display card3 to verify Stephen was not deleted by removeName: method
NSLog(@"card3 info:");
[card3 printAll];
}
return 0;
}
// AddressBook.h
#import <Foundation/Foundation.h>
#import "AddressCard.h"
@interface AddressBook: NSObject
@property (nonatomic, copy) NSString *bookName;
@property (nonatomic, strong) NSMutableArray *book;
-(id) initWithName: (NSString *) name;
-(BOOL) removeName: (NSString *) theName;
-(void) addCard: (AddressCard *) theCard;
-(void) addCard2: (AddressCard *) theCard;
-(void) removeCard: (AddressCard *) theCard;
-(AddressBook *) lookup: (NSString *) theName;
-(int) entries;
-(void) list;
-(void) sort;
-(void) printCards;
@end
// AddressBook.m
#import "AddressBook.h"
@implementation AddressBook
@synthesize bookName, book;
-(id) initWithName: (NSString *) name
{
self = [super init];
if (self) {
bookName = [NSString stringWithString: name];
book = [NSMutableArray array];
}
return self;
}
-(id) init
{
return [self initWithName: @"NoName"];
}
-(BOOL) removeName: (NSString *) theName
{
AddressBook *results = [self lookup: theName];
AddressCard *holder;
if (results.book.count == 1) {
for ( AddressCard *nextCard in book ) {
if ( [nextCard search: theName])
holder = nextCard;
}
[self removeCard: holder];
return YES;
}
return NO;
}
-(void) addCard: (AddressCard *) theCard
{
[book addObject: theCard];
}
-(void) addCard2: (AddressCard *) theCard //with ownership
{
AddressCard *holder = [AddressCard createWithAddressCard: theCard];
[book addObject: holder];
}
-(void) removeCard: (AddressCard *) theCard
{
[book removeObjectIdenticalTo: theCard];
}
-(AddressBook *) lookup: (NSString *) theName
{
AddressBook *results = [[AddressBook alloc] initWithName: @"lookup results"];
for ( AddressCard *nextCard in book ) {
if ( [nextCard search: theName])
[results addCard: nextCard];
}
if (results.book.count == 0)
return nil;
return results;
}
-(int) entries
{
return (int)[book count];
}
-(void) list
{
NSLog (@"======== Contents of: %@ =========", bookName);
for ( AddressCard *theCard in book )
NSLog (@"%-20s %-32s", [theCard.name UTF8String], [theCard.email UTF8String]);
NSLog (@"==================================================");
}
-(void) sort
{
[book sortUsingSelector: @selector(compareNames:)];
}
-(void) printCards
{
NSLog (@"======== Contents of: %@ =========", bookName);
for ( AddressCard *theCard in book ) {
NSLog (@"====================================");
NSLog (@"| |");
NSLog (@"| %-31s |", [theCard.name UTF8String]);
NSLog (@"| %-31s |", [theCard.firstname UTF8String]);
NSLog (@"| %-31s |", [theCard.lastname UTF8String]);
NSLog (@"| %-31s |", [theCard.address UTF8String]);
NSLog (@"| %-31s |", [theCard.city UTF8String]);
NSLog (@"| %-31s |", [theCard.zip UTF8String]);
NSLog (@"| %-31s |", [theCard.country UTF8String]);
NSLog (@"| %-31s |", [theCard.phone UTF8String]);
NSLog (@"| %-31s |", [theCard.email UTF8String]);
NSLog (@"| |");
NSLog (@"| |");
NSLog (@"| |");
NSLog (@"====================================");
NSLog (@" ");
}
}
@end
// AddressCard.h
#import <Foundation/Foundation.h>
@interface AddressCard: NSObject
@property (copy, nonatomic) NSString *name, *firstname, *lastname, *address, *city, *zip, *country, *phone, *email;
-(id) initWithName: (NSString *) name_;
+(AddressCard *) createWithAddressCard: (AddressCard *) theCard;
-(void) setName: (NSString *) theName andEmail: (NSString *) theEmail;
-(void) setName: (NSString *) theName andEmail: (NSString *) theEmail andAddress: (NSString *) theAddress andCity: (NSString *) theCity
andZip: (NSString *) theZip andCountry: (NSString *) theCountry andPhone: (NSString *) thePhone;
-(void) print;
-(void) printAll;
-(BOOL) search: (NSString *) criteria;
-(NSComparisonResult) compareNames: (id) element;
@end
// AddressCard.m
#import "AddressCard.h"
@implementation AddressCard
@synthesize name, firstname, lastname, address, city, zip, country, phone, email;
-(id) initWithName: (NSString *) name_
{
self = [super init];
if (self) {
name = [NSString stringWithString: name_];
NSRange space = [[self name] rangeOfString: @" "];
firstname = [[self name] substringToIndex: space.location];
lastname = [[self name] substringFromIndex: space.location + 1];
address = @" ";
city = @" ";
zip = @" ";
country = @" ";
phone = @" ";
email = @" ";
}
return self;
}
-(id) init
{
return [self initWithName: @"noFirstName orLastName"];
}
+(AddressCard *) createWithAddressCard: (AddressCard *) theCard
{
AddressCard *result = [[AddressCard alloc] init];
result.name = [NSString stringWithString: theCard.name];
NSRange space = [[result name] rangeOfString: @" "];
result.firstname = [[result name] substringToIndex: space.location];
result.lastname = [[result name] substringFromIndex: space.location + 1];
result.address = [NSString stringWithString: theCard.address];
result.city = [NSString stringWithString: theCard.city];
result.zip = [NSString stringWithString: theCard.zip];
result.country = [NSString stringWithString: theCard.country];
result.phone = [NSString stringWithString: theCard.phone];
result.email = [NSString stringWithString: theCard.email];
return result;
}
-(void) setName: (NSString *) theName andEmail: (NSString *) theEmail
{
self.name = theName;
NSRange space = [[self name] rangeOfString: @" "];
self.firstname = [[self name] substringToIndex: space.location];
self.lastname = [[self name] substringFromIndex: space.location + 1];
self.email = theEmail;
self.address = @" ";
self.city = @" ";
self.zip = @" ";
self.country = @" ";
self.phone = @" ";
}
-(void) setName: (NSString *) theName andEmail: (NSString *) theEmail andAddress: (NSString *) theAddress andCity: (NSString *) theCity
andZip: (NSString *) theZip andCountry: (NSString *) theCountry andPhone: (NSString *) thePhone
{
self.name = theName;
NSRange space = [[self name] rangeOfString: @" "];
self.email = theEmail;
self.firstname = [[self name] substringToIndex: space.location];
self.lastname = [[self name] substringFromIndex: space.location + 1];
self.address = theAddress;
self.city = theCity;
self.zip = theZip;
self.country = theCountry;
self.phone = thePhone;
}
-(void) print
{
NSLog (@"====================================");
NSLog (@"| |");
NSLog (@"| %-31s |", [name UTF8String]);
NSLog (@"| %-31s |", [email UTF8String]);
NSLog (@"| |");
NSLog (@"| |");
NSLog (@"| |");
NSLog (@"====================================");
}
-(void) printAll
{
NSLog (@"====================================");
NSLog (@"| |");
NSLog (@"| %-31s |", [name UTF8String]);
NSLog (@"| %-31s |", [firstname UTF8String]);
NSLog (@"| %-31s |", [lastname UTF8String]);
NSLog (@"| %-31s |", [address UTF8String]);
NSLog (@"| %-31s |", [city UTF8String]);
NSLog (@"| %-31s |", [zip UTF8String]);
NSLog (@"| %-31s |", [country UTF8String]);
NSLog (@"| %-31s |", [phone UTF8String]);
NSLog (@"| %-31s |", [email UTF8String]);
NSLog (@"| |");
NSLog (@"| |");
NSLog (@"| |");
NSLog (@"====================================");
}
-(BOOL) search: (NSString *) criteria
{
if ( [self.name rangeOfString: criteria options: NSCaseInsensitiveSearch].location != NSNotFound)
return YES;
else if ( [self.address rangeOfString: criteria options: NSCaseInsensitiveSearch].location != NSNotFound)
return YES;
else if ( [self.city rangeOfString: criteria options: NSCaseInsensitiveSearch].location != NSNotFound)
return YES;
else if ( [self.zip rangeOfString: criteria options: NSCaseInsensitiveSearch].location != NSNotFound)
return YES;
else if ( [self.country rangeOfString: criteria options: NSCaseInsensitiveSearch].location != NSNotFound)
return YES;
else if ( [self.phone rangeOfString: criteria options: NSCaseInsensitiveSearch].location != NSNotFound)
return YES;
else if ( [self.email rangeOfString: criteria options: NSCaseInsensitiveSearch].location != NSNotFound)
return YES;
return NO;
}
-(NSComparisonResult) compareNames: (id) element
{
return [name compare: [element name]];
}
@end
Output:======== Contents of: Linda’s Address Book =========
Julia Kochan jewls337@axlc.com
Tony Iannino tony.iannino@techfitness.com
Stephen Kochan steve@classroomM.com
Jamie Baker jbaker@classroomM.com
Ella Smith ella.smith@csmithent.com
==================================================
Julia Kochan card changed from card1
card1 info:
====================================
| |
| Card1 test |
| Card1 |
| test |
| test |
| test |
| test |
| test |
| test |
| test |
| |
| |
| |
====================================
======== Contents of: Linda’s Address Book =========
Julia Kochan jewls337@axlc.com
Tony Iannino tony.iannino@techfitness.com
Stephen Kochan steve@classroomM.com
Jamie Baker jbaker@classroomM.com
Ella Smith ella.smith@csmithent.com
==================================================
remove: steve
remove successful
======== Contents of: Linda’s Address Book =========
Julia Kochan jewls337@axlc.com
Tony Iannino tony.iannino@techfitness.com
Jamie Baker jbaker@classroomM.com
Ella Smith ella.smith@csmithent.com
==================================================
card3 info:
====================================
| |
| Stephen Kochan |
| Stephen |
| Kochan |
| |
| |
| |
| |
| |
| steve@classroomM.com |
| |
| |
| |
====================================