Amazon.com Widgets Program 15.13
Welcome, Guest. Please login or register.
Did you miss your activation email?
May 22, 2013, 10:39:56 AM
Home Help Search chat Login Register   
News: Read this please.The Great Kangaroo Escape Looking for reviews of the 4th ed on Amazon!   Twitter:  @skochan
                     

+  Official Forum for Programming in Objective-C (the iPhone Programming Language) - Stephen Kochan
|-+  Old Stuff
| |-+  Program Examples
| | |-+  Chapter 15
| | | |-+  Program 15.13
Pages: [1]   Go Down
Print
Author Topic: Program 15.13  (Read 2777 times)
TotalLuck
Full Member
***
Posts: 107



WWW Email




« on: February 15, 2009, 04:13:47 PM »

Sort Method interface
Code: (Objective-C)
-(void) sort;
[/pre]

compare interface
Code: (Objective-C)
-(NSComparisonResult) compareNames: (id) element;
[/pre]

Sort Method implementation
Code: (Objective-C)
-(void) sort
{
[book sortUsingSelector: @selector (compareNames:)];
}
[/pre]

compare Implementation
Code: (Objective-C)
-(NSComparisonResult) compareNames: (id) element
{
return [name compare: [element name]];
}
[/pre]


Test Program
Code: (Objective-C)

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";
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 *card3 = [[ AddressCard alloc] init];
AddressCard *card4 = [[ AddressCard alloc] init];

// set up Four addressCards

[card1 setName: aName andEmail: aEmail];
[card2 setName: bName andEmail: bEmail];
[card3 setName: cName andEmail: cEmail];
[card4 setName: dName andEmail: dEmail];

AddressBook *myBook = [ AddressBook alloc];
AddressCard *myCard;

// Now initialize the Adress Book
myBook = [ myBook initWithName:@"Linda's Address Book"];

//add some cards to the address book
[myBook addCard: card1];
[myBook addCard: card2];
[myBook addCard: card3];
[myBook addCard: card4];

// list the unsorted book
[myBook list];

//sort it and list it again

[myBook sort];
[myBook list];

[card1 release];
[card2 release];
[card3 release];
[card4 release];

[pool drain];

return 0;

}
[/pre]
Logged

Apps available on  iTunes store:
"ADACode"  iPhone and iPad versions, "ADAGuidelines" iPhone & iPad versions,  "Rehabilitation Act of 1973" for iPhone
"APokerTimer" now for iPhone http://bit.ly/h1fAJp
kevinsmak
Newbie
*
Posts: 4






« Reply #1 on: August 31, 2009, 12:40:39 PM »

Can't get this to work, it's tough cause the book I feel doesn't give the information needed for the .h & .m files but I understand they need to watch space, forum example still doesn't show it.  I'm getting error: 'Name' undeclared (first use in this function).  If anyone can help me with what I'm missing, it's driving me crazy...

AddressBook.h
Code: (Objective-C)
#import <Foundation/NSArray.h>
#import "AddressCard.h"

@interface AddressBook : NSObject
{
NSString *bookName;
NSMutableArray *book;
}

-(NSComparisonResult) compareNames: (id) element;
-(AddressBook *) initWithName: (NSString *) name;
-(void) sort;
-(void) addCard: (AddressCard *) theCard;
-(void) removeCard: (AddressCard *) theCard;

-(AddressCard *)lookup: (NSString *) theName;
-(int) entries;
-(void) list;

@end

AddressBook.m
Code: (Objective-C)
#import "AddressBook.h"

@implementation AddressBook

//Set up the addressbook's name and an empty book

-(AddressCard *) lookup: (NSString *) theName
{
for (AddressCard *nextCard in book)
if ([[nextCard name] caseInsensitiveCompare: theName] == NSOrderedSame)
return nextCard;

return nil;
}

-(void) sort
{
[book sortUsingSelector: @selector (compareNames:)];
}

//Compare the two names from the specified address cards

-(NSComparisonResult) compareNames: (id) element
{
return [name compare: [element name]]; [color=red]//Error:'Name' undeclared (first use in this function[/color]
}

-(void) removeCard: (AddressCard *) theCard
{
[book removeObjectIdenticalTo: theCard];
}


-(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

TestFile.m
Code: (Objective-C)
#import "AddressBook.h"
#import <Foundation/NSAutoreleasePool.h>

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

NSString *aName = @"Julia Kochan";
NSString *aEmail = @"jewls334@axlc.com";
NSString *bName = @"Tony Iannino";
NSString *bEmail = @"Tony.iannion@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 *card3 = [[AddressCard alloc] init];
AddressCard *card4 = [[AddressCard alloc] init];

AddressBook *myBook = [AddressBook alloc];

// 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];

myBook = [myBook initWithName: @"Linda's Address Book"];

//Add some cards to the address book

[myBook addCard: card1];
[myBook addCard: card2];
[myBook addCard: card3];
[myBook addCard: card4];

//List the unsorted book

[myBook list];

//Sort it and list it again

[myBook sort];
[myBook list];


[card1 release];
[card2 release];
[card3 release];
[card4 release];
[myBook release];

[pool drain];
    return 0;
}


Thanks!
Logged
skochan
Administrator
Hero Member
*****
Posts: 3103







« Reply #2 on: August 31, 2009, 07:15:35 PM »

Hi,

The compareNames: method will be called whenever the sort routine needs to compare two objects in the AddressBook's book array.  Those objects are AddressCard's.  Therefore, the compareNames: method should be implemented in the AddressCard class, and not in the AddressBook class.

Cheers,

Steve Kochan
« Last Edit: August 31, 2009, 08:47:38 PM by skochan » Logged
kevinsmak
Newbie
*
Posts: 4






« Reply #3 on: August 31, 2009, 08:12:39 PM »

Thank you so much!  Got it to work.
Logged
cshutchinson
Newbie
*
Posts: 3


Email




« Reply #4 on: December 06, 2009, 10:08:56 AM »

On page 365 of the 6th printing, Stephen makes the statement:

"Note that the sort is an ascending one. However you can easily perform a descending sort by modifying the compareNames: method in the AdressCard class to reverse the sense of the values that are returned..."

I struggled after reading this because I wanted to do exactly what was suggested, reverse the sort order. It took me a long time to figure out how to do the reverse sort. I was embarrassed when I finally figured it out with the modified method below:

Code: (Objective-C)
-(NSComparisonResult) compareNames: (id) element {
return [[element name] compare: name];

It brought a smile to my face to see it reverse sort!

I am still confused a little about the @selector(compareNames:) portion of the AddressBook sort method.  When you look at the compareNames implementation in AddressCard, you see that the method is expecting an (id) to be passed to the method. But, when it is called from sort, no (id) is passed... This is confusing me to no end.  Can anyone shed some light on how this actually works?

It seems if you have:

Code: (Objective-C)
-(void) sort
{
[book sortUsingSelector: @selector(compareNames:)];
}

but no object follows the : in the selector that the method compareNames would not receive an argument as it should....

Can anyone clear this up?

Logged
skochan
Administrator
Hero Member
*****
Posts: 3103







« Reply #5 on: December 06, 2009, 11:25:30 AM »

The directive @selector creates an argument of type SEL, which is the type of argument expected by the sortUsingSelector: method.   This is the way the Objective-C system allows you to pass a reference to a method as an argument to another method (see page 197).   

As noted on page 141-143, a method called compareNames would indicate a method that takes no arguments, while one named compareNames: indicates one that takes a single argument.   

Hope this helps.

Cheers,

Steve Kochan
Logged
cshutchinson
Newbie
*
Posts: 3


Email




« Reply #6 on: December 06, 2009, 01:11:40 PM »

Thank you! I appreciate your help as you certainly go beyond the call of duty to help your readers!
Logged
murell
Newbie
*
Posts: 2






« Reply #7 on: January 26, 2010, 06:23:40 PM »

Can someone please provide further clarification on the ways to adjust how the array is sorted? I am having trouble grasping why switching name and [element name] in the comparenames: method would reverse the sort order? My understanding is that the return type NSComparisonResult is sent back to the sort method after each comparison. If the same elements are being compared, shouldn't the result be the same regardless of the order in which they are compared?

Perhaps what I'm really missing is how the methods work together? My understanding is that the sort method is sending items, one by one in order, from the book array to be compared in the compareNames: method.

Any clarification on how the ascending or descending ordering works would be appreciated.
Logged
rgronlie
Global Moderator
Full Member
*****
Posts: 212







« Reply #8 on: January 26, 2010, 09:44:02 PM »

The sortUsingSelector: method attempts to sort the array in ascending order. The method assumes that you are comparing name to [element name] (What is name relative to [element name]). When you reverse that and compare [element name] to name (What is [element name] relative to name) you'll get the opposite result (NSOrderedDescending instead of NSOrderedAscending and vice-versa) and sortUsingSelector: will end up sorting the array in the opposite order.

Ryan
Logged

Sanity: Minds are like parachutes. Just because you've lost yours doesn't mean you can borrow mine.
murell
Newbie
*
Posts: 2






« Reply #9 on: January 28, 2010, 12:50:14 AM »

I have finally grasped the concept! Thank you so much for your quick reply.
Logged
Pages: [1]   Go Up
Print
Jump to:  



Login with username, password and session length

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Entire forum contents (c) 2009 classroomM.com. All rights reserved.