Block語法
Block:塊語法,本質上是匿名函數(沒有名稱的函數)
標準C⾥⾯沒有Block,C語⾔的後期擴展版本,加⼊了匿名函數。
C++、JS、Swift等語⾔,有類似語法,叫做閉包。
Block語法和函數指針很相似
函數
C語⾔中,實現某⼀功能的代碼段。
完整的函數包含兩部分:函數聲明、函數定義
函數聲明,即函數原型。例如:int sum(int x,int y);具有兩個整型參數,⼀個整型返回值的函數。
函數定義,即函數實現。例如:
int sum(int x,int y){
retrun x + y;
}
函數指針
函數指針(變量):存放函數地址(函數名)的指針變量。
int (*p)(int x,int y) = sum;
函數指針類型:int (*)(int x,int y) 即:指向 兩個整型參數,⼀個整型返回值 函數 的指針。
函數指針變量:p
函數指針的值:sum
Block
匿名函數:沒有名稱的函數。
例如 :
int (int x, int y)
沒有名稱的函數應該如何調⽤?(有名稱的話,可以直接調⽤,也可以通過函數指針來調⽤)
因爲Block是匿名函數,block變量存放的函數的實現,通過block變量能直接調⽤函數
Block類型:int (^)(int)
Block變量:myBlock
Block值:^ int (int num){ return 7 * num;}
即:^ 返回值類型 (參數列表){函數體} 其中 返回值類型可以省略。
Block使⽤
int (^block1)(int x,int y) = ^(int x,int y){
return x + y;
};
int a = block1(32 , 34);//block的使⽤和函數指針的使⽤類似。
NSLog(@“%d”,a);
typedef
typedef int (^BlockType)(int x,int y)
原類型:int (^)(int x,int y)
新類型:BlockType
//Block塊的typedef
typedef int (^myBlock)(int,int);
myBlock mb = ^(int a,int b){
return a+b;
};
NSLog(@"%d",mb(3,6));
Block塊參數省略時,裏面可以寫多個任意類型的參數,但返回值類型必須是int
typedef int (^myBlock)();
myBlock mb3 = ^(int a,int b,int c){
return a+b+c;
};
NSLog(@"%d",mb3(3,6,9));
description方法/NSLog函數
1.description方法是NSObject自帶的方法,包括類方法和對象方法
+ (NSString *)description; // 默認返回類名
- (NSString *)description; // 默認返回<類名:內存地址>
2.默認情況下利用NSLog和%@輸出對象的時返回的就是類名和內存地址
3.修改NSLog和%@的默認輸出:重寫類對象或者實例對象的description方法即可。
因爲NSLog函數進行打印的時候會自動調用description方法
/********** Person.h文件***********/
#import <Foundation/Foundation.h>
@interface Person : NSObject
+ (NSString *)description;
- (NSString *)description;
@property int age;
@property NSString *name;
@end
/*********** Person.m文件***********/
#import "Person.h"
@implementation Person
#pragma mark 類對象輸出的結果
+ (NSString *)description{
return @"AAA";
}
#pragma mark 實例對象輸出的結果
- (NSString *)description{
// NSLog(@"%@",self); 引發死循環
return [NSString stringWithFormat:@"name = %@ age = %d",_name,_age];}
@end
/**************main.m文件***********/
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]){
Class c = [Person class];
NSLog(@"%@",c);
Person *person = [[Person alloc] init];
person.name = @"John";
person.age = 20; //執行NSLog函數的時候會調用description方法默認返回<類名/對象名: 地址>
NSLog(@"%@",person);
}
/*********** 豐富日誌輸出 ***********/
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]){
//打印person對象地址
Person *person = [[Person alloc] init];
NSLog(@"%@",person); // <Person: 0x100200ae0>
// 打印person指針的地址
NSLog(@"%p",person); // 0x100200ae0 對象和指針地址一致
// 指針變量的地址
NSLog(@"%p",&person);// 0x7fff5fbff8e8
// NSLog用%s無法輸出帶有中文的文件路徑,可以用c語言中的printf和%s來代替
// NSLog(@"%s",__FILE__);
printf("%s",__FILE__); //輸出當前方法
NSLog(@"%s",__FUNCTION__); // 返回 main
}
Block實現數組排序
main.h
/*
0、按年齡升序排列
1、按學號升序排列
2、按學號降序排列
3、按姓名升序排列
4、按姓名降序排列
*/
Student *stu1 = [Student studentWithName:@"ZhangSan" age:18 num:2];
Student *stu2 = [Student studentWithName:@"LiSi" age:20 num:1];
Student *stu3 = [Student studentWithName:@"WangWu" age:10 num:3];
NSMutableArray *arr = [NSMutableArray arrayWithObjects:stu1,stu2,stu3, nil];
//因爲重寫了description方法,能夠輸出對象數組的詳細信息,而不是隻輸出一個首地址
NSLog(@"%@",arr);
//通過遍歷實現打印對象數組
for (Student *stu in arr) {
[stu introduce];
}
//0、按年齡升序排列
NSLog(@"--------年齡升序----------");
//此方法不好,代碼量過大,其實可以直接return [stu1 age] > [stu2 age],因爲有NSComparisonResult的存在會自動把返回值變成NSComparisonResult類型的
[arr sortUsingComparator:^NSComparisonResult(id obj1,id obj2){
//數組排序方法:sortUsingComparator,裏面應該是封裝了雙層for循環,參數是一個返回值爲NSComparisonResult類型的Block塊
Student *stu1 = (Student *)obj1;//此處用於說明接收的是Student類類型的參數
Student *stu2 = (Student *)obj2;
if([stu1 age] > [stu2 age]){
return NSOrderedDescending;//降序
}
else if([stu1 age] < [stu2 age]){
return NSOrderedAscending;//升序
}
else {
return NSOrderedSame;//相等
}
}];
NSLog(@"%@",arr);
//1、按學號升序排列
NSLog(@"--------學號升序----------");
//用NSComparator類型的sort1接收NSComparisonResult類型的結果
//因爲:typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);
NSComparator sort1 = ^(id obj1,id obj2){
Student *stu1 = (Student *)obj1;
Student *stu2 = (Student *)obj2;
if ([stu1 num] > [stu2 num]) {
return NSOrderedDescending;
}
else if([stu1 num] < [stu2 num]){
return NSOrderedAscending;
}
else{
return NSOrderedSame;
}
};
[arr sortUsingComparator:sort1];
for (Student *stu in arr) {
[stu introduce];
}
//2、按學號降序排列
NSLog(@"--------學號降序----------");
/*
NSComparator sort2 = ^(id obj1,id obj2){
Student *stu1 = (Student *)obj1;
Student *stu2 = (Student *)obj2;
if ([stu1 num] > [stu2 num]) {
return NSOrderedDescending;
}
else if([stu1 num] < [stu2 num]){
return NSOrderedAscending;
}
else{
return NSOrderedSame;
}
};
*/
NSComparator sort2 = ^NSComparisonResult(Student *stu1,Student *stu2){
return [stu1 num] < [stu2 num];//與升序相比只需要把 > 換成 < 就行了
};
[arr sortUsingComparator:sort2];
for (Student *stu in arr) {
[stu introduce];
}
//3、按姓名升序排列
NSLog(@"--------姓名升序----------");
/*
NSComparator sort3 = ^(id obj1,id obj2){
Student *stu1 = (Student *)obj1;
Student *stu2 = (Student *)obj2;
return [[stu1 name] compare: [stu2 name]];
};
*/
//此處直接用Student作爲參數,則內部不需要再寫Student *stu1 = (Student *)obj1;用來接收
NSComparator sort3 = ^(Student * stu1,Student * obj2){
return [[stu1 name] compare: [stu2 name]];//字符串類型比較要用compare:方法,返回值直接是NSComparisonResult類型的
};
[arr sortUsingComparator:sort3];
for (Student *stu in arr) {
[stu introduce];
}
//4、按姓名降序排列
NSLog(@"--------姓名降序----------");
NSComparator sort4 = ^(id obj1,id obj2){
Student *stu1 = (Student *)obj1;
Student *stu2 = (Student *)obj2;
return -[[stu1 name] compare: [stu2 name]];
};
[arr sortUsingComparator:sort4];
NSLog(@"%@",[arr description]);//重寫了系統自帶的description方法,可以直接輸出數組的值,而不是隻有每個對象的首地址
/*
for (Student *stu in arr) {
[stu introduce];
}
*/
Student.h
@interface Student : NSObject
{
NSString * _name;
NSInteger _age;
NSInteger _num;
}
@property(nonatomic,retain)NSString * name;
@property(nonatomic,assign)NSInteger age;
@property(nonatomic,assign)NSInteger num;
-(instancetype)initWithName:(NSString *)name
age:(NSInteger)age
num:(NSInteger)num;
+(instancetype)studentWithName:(NSString *)name
age:(NSInteger)age
num:(NSInteger)num;
//自我介紹
-(void)introduce;
//系統自帶方法,重寫時就不需要聲明瞭
//-(NSString *)description;
@end
Student.m
@implementation Student
-(instancetype)initWithName:(NSString *)name
age:(NSInteger)age
num:(NSInteger)num{
self = [super init];
if (self) {
_name = name;
_age = age;
_num = num;
}
return self;
}
+(instancetype)studentWithName:(NSString *)name
age:(NSInteger)age
num:(NSInteger)num{
Student *stu = [[Student alloc]initWithName:name age:age num:num];
return stu;
}
-(void)introduce{
NSLog(@"My name is %@,%ld years old,StudyNum is %ld",_name,_age,_num);
}
//重寫description方法
-(NSString *)description{
return [NSString stringWithFormat:@"name:%@,age:%ld,num:%ld",_name,_age,_num];
}
@end
字面量:語法糖
Literals (字⾯量),是⼀種簡易表⽰值的⽅法
未使用字面量 | 使用字面量 |
---|---|
NSString *str1 = [NSString stringWithFormat:@”234”]; | NSString *str2 = @”234”; |
NSArray *array = [NSArray arrayWithObject:a,b,c,nil]; | NSArray *array = @[a,b,c]; |
[array objectAtIndex:1] | array[1] |
NSDictionary *dict = dictionnaryWithObjectAndKeys:@”laowang”,@”name”,@”man”,@”sex”,nil; | NSDictionary *dict = @{@”name”:@”laowang”,@”sex”:@”man”}; |
[dict valueForKey:k] | dict[k] |