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;