首页 > 代码库 > block的用法和数组排序(高级)
block的用法和数组排序(高级)
block的用法和数组排序(高级)
一, block
我们都知道函数只可以嵌套调用,但决不允许函数的嵌套定义,这有时给我们带来了很大的不便,而OC提供的block用法为我们解决了这个问题,下面简单说一下1,block的用法:
(1)block是用来存储函数,所以给block赋值时赋的是整个函数的实现,例如,要在main函数里写一个求两个数的和的函数,返回值为整型,参数为两个整型,通常在函数外面会这样写
int sum(int x, int y)
{
return x + y;
}
如果要在函数内部写就需要用到block语句写法如下:
int (^sum)(int x,int y) = ^(int x, int y)
{
return x + y;
};
block 变量的类型是: int (^)(int x,int y) (这里的”(^)”是系统规定的block写法) sum是block变量的名字, "="号右边的
^(int x, int y)
{
return x + y;
};
是block变量的初始值,
当把函数的实现赋给block后,block变量sum就可以当做函数名使用
如: NSLog(@"sum = %d",sum (5,10));
从block的定义可以看出它跟函数指针的定义很相似,唯一不同就是函数指针的类型定义时是用(*),而block是用(^).
(2),此外当在block外面定义了变量(局部变量),如果没有在变量前加上"__block"修饰,则在block内部无法对该变量修改,在block内部系统识别该变量是readonly不可修改的,如果要修改block外边的变量,必须将该变量用"__block"修饰.block外部的局部变量被"__block"修饰后在block内部告诉编译器不要再把该变量当做常量来看待,但是若在block内部访问全局变量,则不需要用__block修饰,有关全局变量下面可以再详细的叙述一下;
(3), 如果使用block时对它的定义感觉麻烦,我们也可以使用typedef对它的类型重定义 如: typedefint(^BLOCK) (int x, int y);这样如果再定义该类型的block,只需要使用BLOCK代替int (^)(int x,int y)即可.
(4), 对于全局变量:在一个文件里定义了一个全局变量例如:(int a = 10;),如果在其他文件里想用该变量a(如果在main函数里也定义了int a,则编译时会失败,因为系统编译的时.m文件,而main函数也是.m文件,在同样的.m文件里同时出现两个变量名相同的变量,系统是不允许的),则需要在要调用该变量的文件里声明一下即用 externint a;他会告诉编译器,这个变量a已经在其他文件里定义了. 如果在每个文件了都定义了同一个名的变量,又只想在本文件里使用,需要给变量声明为static即定义为静态变量(此时系统识别变量是以static int去找到地址取出其中的数据的).
二, 数组排序
1,首先建立一个人类
在.h文件里定义实例变量和方法声明
{
NSString *_name; //姓名
CGFloat _height; //身高
NSInteger _age; //年龄
}
//初始化
- (id)initWithname:(NSString *)name age:(NSInteger)age height:(CGFloat)height;
//setter
- (void)setName:(NSString *)name;
- (void)setHeight:(CGFloat)height;
- (void)setAge:(NSInteger)age;
//getter
- (NSString *)name;
- (CGFloat)height;
- (NSInteger)age;
在.m文件里
//setter
- (void)setName:(NSString *)name
{
_name = name;
}
- (void)setHeight:(CGFloat)height
{
_height = height;
}
- (void)setAge:(NSInteger)age
{
_age = age;
}
//getter
- (NSString *)name
{
return_name;
}
- (CGFloat)height
{
return_height;
}
- (NSInteger)age
{
return_age;
}
#pragma mark - override method
//重写description
- (NSString *)description
{
return [NSStringstringWithFormat:@"name = %@, age = %ld,height = %.2f",_name,_age,_height];
}
#pragma mark - initmethod
- (id)initWithname:(NSString *)name age:(NSInteger)age height:(CGFloat)height
{
self = [superinit];
if (self != nil) {
_name = name;
_age = age;
_height = height;
}
returnself;
}
我们在main函数内创建几个人类的对象,用一个数组personArr存储
Person *per1 = [[Personalloc] initWithname:@"Frank"age:20height:175];
Person *per2 = [[Personalloc] initWithname:@"Duke"age:25height:170];
Person *per3 = [[Personalloc] initWithname:@"Lili"age:22height:165];
Person *per4 = [[Personalloc] initWithname:@"Mary"age:18height:160];
存储对象
NSArray *personArr = [[NSArrayalloc] initWithObjects:per1,per2,per3,per4, nil];
若想为人分别按照年龄,身高升序排序,按照姓名降序排序,则需要添加方法,如下:
//添加比较的方法 compare
//按年龄升序排序
- (NSComparisonResult)personAge:(Person *)anotherPerson;
-
//按身高升序排序
- (NSComparisonResult)personHeight:(Person *)anotherPerson;
//按姓名降序排序
- (NSComparisonResult)personNameDescending:(Person *)anotherPerson;
在.m文件对方法实现:
//按年龄升序排序
- (NSComparisonResult)personAge:(Person *)anotherPerson
{
if ([selfage] > [anotherPerson age]) {
returnNSOrderedDescending; //1
} elseif ([selfage] == [anotherPerson age])
{
returnNSOrderedSame; //0
} else {
returnNSOrderedAscending; //-1
}
}
//按身高升序排序
- (NSComparisonResult)personHeight:(Person *)anotherPerson
{
if ([selfheight] > [anotherPerson height]) {
returnNSOrderedDescending; //1
} elseif ([selfheight] == [anotherPerson height])
{
returnNSOrderedSame; //0
} else {
returnNSOrderedAscending; //-1
}
}
//按姓名降序排序
- (NSComparisonResult)personNameDescending:(Person *)anotherPerson
{
return -[[selfname] compare:[anotherPerson name]];
}
在main函数中调用
//对数组元素按年龄升序排序
NSArray *sortAge = [personArr sortedArrayUsingSelector:@selector(personAge:)];
NSLog(@"%@",sortAge);
//对数组元素按身高升序排序
NSArray *sortHeight = [personArrsortedArrayUsingSelector:@selector(personHeight:)];
NSLog(@"%@",sortHeight);
//对数组元素按姓名序排序
NSArray *sortNameDe = [personArrsortedArrayUsingSelector:@selector(personNameDescending:)];
NSLog(@"%@",sortNameDe);
三,对数组的元素降序排序和升序排序
NSArray *arr = [[NSArrayalloc] initWithObjects:@"ff",@"bb",@"aa",@"dd", nil];
对数组元素升序排序
NSArray *sortArrAscending = [arrsortedArrayUsingSelector:@selector(compare:)];
NSLog(@"%@",sortArrAscending);
//对数组元素降序排序
//通过block排序
NSArray *sortAscending = [arr sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
//对block匿名函数实现比较方法
//1)将id类型转为NSString *类型
NSString *str1 = (NSString *)obj1;
NSString *str2 = (NSString *)obj2;
//字符串比较
return -[str1 compare:str2];
}];
NSLog(@"%@",sortAscending);
综上所述:
(1),sortedArrayUsingSelector:排序适用于升序排序以及自定义的类排序
(2),block(sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2))排序方式适用于当数组中的对象类型是系统类型(即系统提供的OC类型)时,并且要降序排序时
系统提供的排序方法sortedArrayUsingSelector:还是利用冒泡排序法,只是把 if 里的(compare)判断条件中的要比较的对象空出来了,大于零的条件(return 1)已经给定,也就是按照升序排序,如果前者大于后者,则交换位置
系统提供的排序方法sortedArrayUsingComparator:^NSComparisonResult(idobj1, id obj2)也是利用冒泡排序法,它跟sortedArrayUsingSelector:不同,他把if 里的判断条件中的要比较的对象类型让我们自己选择,既可以是任何对象类型, obj1和obj2就是让我们自己选择的,大于零的条件已经给定,但是 > 0的返回值也让我们自己选择,也就是按照升序或者降序排序有我们自己决定,如果降序排序,则返回值为-1,若为升序返回值为1;