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