在AddressBook类中添加sort方法,利用NSMutableArray类中的sortUsingSelector:方法可以很容易实现这项功能。sortUsingSelector:方法会使用参数selector比较两个参数。由于数组可以包含任何类型的对象,所以实现一般的排序方法,唯有就是由你来判断数组中的元素是否有序,为此,你必须添加一个方法比较数组中的两个元素。这个方法返回的结果是NSCompareResult类型的值。如果希望将第一个元素放在第二元素之前,那么方法的返回值应该是NSOrderedAscending。如果认为两个元素相等,那么返回NSorderedSame。如果排序后得数组中,第一个元素应该放在第二个元素之后,那么返回NSOrderedDescending。
首先在AddressBook类中添加sort方法:
-(void) sort
{
[book sortUsingSelector: @selector(compareNames:) ];
}
@selector(compareNames:)
利用指定的方法名创建一个SEL类型的selector。selector可以叫做选择器,其实指的就是对象的方法,也可以理解为C语言里面的函数指针,在面向对象里面的对应概念。
[self performSelector:@selector(Hidden) withObject:nil afterDelay:2.8];//2.8秒之后调用selector里面的函数,很好用
@selector(xxxx)的作用是找到名字为xxxx的方法。一般用于[a performSelector:@selector(b)];就是说去调用a对象的b方法,和[a b];的意思一样,但是这样更加动态一些。@selector(xxxx)返回的类型是SEL,看方法说明的时候如果参数类型是SEL,那么就是要接受@selector(xxxx)返回的值的那种了。
使用方法sortUsingSelector:比较数组中的两个元素时,它会调用指定的方法向数组中的第一个元素(接收者)发送消息,与它的参数 进行比较,返回值为NSComparisonResult类型。因为地址薄的元素为AddressCard类型,还要向Addresscard类添加compareName:方法,如下:
-(NSComparisonResult ) compareName: (id)element
{
return [name compare: [element name]];
}
使用区块排序
NSArray和NSMutbleArray类中具有使用区块对数组中的元素进行排序的方法。
NSArray的排序的方法的一般格式为:
-(NSArray *) sortedArrayUsingComparator: (NSComparator ) block
NSMutableArray的排序方法格式为:
-(void) sortUsingComparator: (NSComparator ) block
NScomparator作为typedef定义在系统的头文件中:
typedef NSComparisonResult (^NSComparator) (id obj1,id obj2);
NSComparator是一个区块,使用里两个对象作为参数,并返回NSComparisonResult类型的值。这个方法因为使用了区块,对大数组排序可能会快些。如果为了速度,可以考虑在程序中使用。这个区块作为参数传递给sortUsingComparator:方法,他可以简单的调用compareName:方法,对地址卡片进行比较
-(void) sort
{
[book sortUsingSelector:
^(id obj1,id obj2){
return [obj1 compareNames: obj2];
} ];
}
这样能够运行,但是并没有能够提升性能,因为区块调用 compareNames:方法和sortUsingComparator: 方法一样。更好的方法是在区块中做更多的工作,是性能提升。-(void) sort
{
[book sortUsingSelector:
^(id obj1,id obj2){
return [[obj1 name] compare: [obj2 name]];
} ];
}
使用区块的sort方法有一个好处,即不必为需要比较的对象添加比较的方法。另一个好处在于如果需要改变进行比较的地址卡片的方式,只需要直接修改sort方法,并不需要对需要比较的对象所属的类进行更改。
常用的NSArray方法
常用的NSMutableArray方法
以上表格中obj、obj1、obj2是任意对象,i是呈现数组中有效的索引号的NSUInteger整数,selector是SEL类型的selector对象,size是一个NSUInteger整数。
NSValue类
以前提到过,像数组这样的Foundation集合只能存储对象,不能存储像int这样的基本数据类型,为了解决这个问题,需要使用NSNumber对象数组。同时还有一种数据类型不是对象,源于C语言的数据类型,它就是结构。例如:CGPoint就是一种结构。
要将结构存储在数组中,不能够直接做到。NSValue类正好可以将结构转化为对象,并把它存储在集合中。这种将结构转化为对象的方式,简称为包装,逆向处理就是从对象中解出基本类型,简称展开。
NSValue包装和展开的方法
以下代码采用了CGPoint结构,将它加入到可变数数组touchPoints中,因为CGPoint是一个结构,并不能够直接将他们存储到touchPoints中,因此,需要先将它们转化成一个对象:
CGPoint myPoint;
NSValue *pointObj;
NSMutableArray *touchPoints = [NSMutableArray array];
...
myPoint.x = 20;
myPoint.y = 100;
pointObj = [NSValue valueWithPoint: myPoint];
[touchPoints addObject: pointObj];
如果期望从数组touchPoints中取出最后一个点并将他转化成CGPoint。语句如下:
myPoint = [[touchPoints lastObject] pointVale];