15.4.2 数组排序

如果地址簿包含大量的记录,那么按字母将其排序可能很方便。通过在AddressBook类中增加sort方法并利用NSMutableArray类中名为sortUsingSelector:的方法,可以很容易地实现这项功能。sort方法使用一个selector作为其参数,sortUsingSelector:方法使用这个selector来比较两个元素。数组可包含任何类型的对象,所以实现一般排序方法的唯一途径就是先判定数组中的元素是否有序。为此,必须添加一个方法用于比较数组中的两个元素[1]这个方法返回的结果是NSComparisonResult类型的值。如果希望排序方法使排序后原数组中的第一条记录位于第二条之前,那么,方法的返回值应是NSOrderedAscending;如果这两条记录相等,那么返回NSOrderedSame;如果排序后的原数组中的第一条记录放在第二条之后,那么返回值NSOrderedDescending。

首先,下面是AddressBook类中的新sort方法:


-(void)sort

{

[book sortUsingSelector:@selector(compareNames:)];

}


和在第9章“多态动态类型和动态绑定”中学到的一样,表达式


@selector(compareNames:)


创建一个SEL类型的selector,它来自一个指定的方法名,sortUsingSelector:使用该方法比较数组中的两个元素。如果sortUsingSelector:方法需要完成这样的比较,它先调用这个指定的selector方法,然后向数组(接收者)的第一条记录发送消息,比较其参数和此记录。前面描述过,返回值应该为NSComparisonResult类型。

因为地址簿的元素是AddressCard对象,所以还必须向AddressCard类添加Comparision方法。因此,应该回到AddressCard类,并为其添加compareNames:方法。下面给出具体实现:


//Compare the two names from the specified address cards

-(NSComparisonResult)compareNames:(id)element

{

return[name compare:[element name]];

}


因为执行的是地址簿中两个名字字符串的比较,所以可以用NSString类的compare:方法来实现此功能。

如果向AddressBook类添加了sort方法,并且向AddressCard类添加了compareNames:方法,那么可以编写一个程序来测试一下(参见代码清单15-13)。

代码清单15-13测试程序


import“AddressBook.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”;

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

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:@“Lindas 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;

}


代码清单15-13输出


========Contents of:Lindas Address Book=========

Julia Kochan jewls337@axlc.com

Tony Iannino tony.iannino@techfitness.com

Stephen Kochan steve@kochan-wood.com

Jamie Baker jbaker@kochan-wood.com

===================================================

========Contents of:Lindas Address Book=========

Jamie Baker jbaker@kochan-wood.com

Julia Kochan jewls337@axlc.com

Stephen Kochan steve@kochan-wood.com

Tony Iannino tony.iannino@techfitness.com

===================================================


应能注意到排列是升序的,但是,可以很容易地修改AddressCard类中的compareNames:方法,使返回的值呈降序排列。

现在,处理数组对象有50多个方法,表15-4和表15-5分别列出了不变数组和可变数组的常用方法。因为NSMutableArray类是NSArray类的子类,所以前者继承了后者的方法。

表15-4和表15-5中的obj、obj1和obj2是任意对象,i是呈现数组中有效索引号的NSUInteger整数,selector是SEL类型的selector对象,size是一个NSUInteger整数。

15.4.2 数组排序 - 图1

15.4.2 数组排序 - 图2

[1]还有一个名为sortUsingFunction:context:的方法,它允许你使用函数代替方法来实现比较功能。