【Objective_C学习笔记】Block的使用
- Block的介绍
- 用于对象之间的通信,通信方式是1对1;
- 是一个匿名的函数代码块,此代码块可以作为参数传递给其他对象;
- 可以把block当做Objective-C的匿名函数,block是OC中的一种数据类型,
^
是block的特有标记。
- Block的格式
(返回类型)(^block名称)(参数类型)=^(参数列表){代码实现};。
说明:如果没有参数,等号后面参数列表的()可以省略。
- Block 的使用
- Block的定义
- (void)viewDidLoad { [super viewDidLoad]; //1、无参数、无返回值的block的定义和使用 void (^myBlock1)() = ^{ NSLog(@"block无返回值,无参数"); }; myBlock1(); //2、无参数、有返回值的block的定义和使用 int (^myBlock2)() = ^{ return 10; }; NSLog(@"myBlock2的返回值是%d", myBlock2()); //3、有参数,有返回值的block定义和使用 int (^myBlock3)(int, int) = ^(int a, int b) { return a + b; }; NSLog(@"myBlock3的返回值是%d", myBlock3(5, 8)); }
运行结果:
2. Block作为方法的参数
将block作为方法的参数,可以用block来封装代码块。
- (void)viewDidLoad { [super viewDidLoad]; //1、无参数、无返回值的block的定义和使用 void (^myBlock1)() = ^{ NSLog(@"block无返回值,无参数"); }; myBlock1(); //2、无参数、有返回值的block的定义和使用 int (^myBlock2)() = ^{ return 10; }; NSLog(@"myBlock2的返回值是%d", myBlock2()); //3、有参数,有返回值的block定义和使用 int (^myBlock3)(int, int) = ^(int a, int b) { return a + b; }; NSLog(@"myBlock3的返回值是%d", myBlock3(5, 8)); //4、作为方法的参数,可以用block来封装代码块。 [self testBlockAsParam:^{ NSLog(@"block作为testBlockAsParam的参数"); }]; } - (void) testBlockAsParam: (void (^)()) block { block(); //执行block内部代码 }
运行结果:
3. Block作为属性
block作为属性,应使用copy修饰。若用weak、assign修饰block属性时,当block所在函数\方法返回\结束,该block就会被销毁。在其他方法内部调用访问该block,就会引发野指针错误EXC_BAD_ACCESS
。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#import "ViewController.h" @interface ViewController () @property (nonatomic,copy) void (^myBlock)(); //block作为属性 @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //1、无参数、无返回值的block的定义和使用 void (^myBlock1)() = ^{ NSLog(@"block无返回值,无参数"); }; myBlock1(); //2、无参数、有返回值的block的定义和使用 int (^myBlock2)() = ^{ return 10; }; NSLog(@"myBlock2的返回值是%d", myBlock2()); //3、有参数,有返回值的block定义和使用 int (^myBlock3)(int, int) = ^(int a, int b) { return a + b; }; NSLog(@"myBlock3的返回值是%d", myBlock3(5, 8)); //4、block作为方法的参数,可以用来封装代码块。 [self testBlockAsParam:^{ NSLog(@"block作为testBlockAsParam的参数"); }]; //5、block作为属性 [self setMyBlock:^{ NSLog(@"block作为属性"); }]; NSLog(@"%@",self.myBlock); self.myBlock();//block作为属性的调用 } - (void) testBlockAsParam: (void (^)()) block { block(); //执行block内部代码 }
运行结果:
4. Block 访问外部变量
- block内部可以访问外部的变量,block默认是将其复制到其数据结构中来实现访问的。
- 默认情况下,block内部不能修改外面的局部变量,因为通过block进行闭包的变量是const的。
- 给局部变量加上
__block
关键字,这个局部变量就可以在block内部修改,block是复制其引用地址来实现访问的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#import "ViewController.h" @interface ViewController () @property (nonatomic,copy) void (^myBlock)(); //block作为属性 @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //1、无参数、无返回值的block的定义和使用 void (^myBlock1)() = ^{ NSLog(@"block无返回值,无参数"); }; myBlock1(); //2、无参数、有返回值的block的定义和使用 int (^myBlock2)() = ^{ return 10; }; NSLog(@"myBlock2的返回值是%d", myBlock2()); //3、有参数,有返回值的block定义和使用 int (^myBlock3)(int, int) = ^(int a, int b) { return a + b; }; NSLog(@"myBlock3的返回值是%d", myBlock3(5, 8)); //4、block作为方法的参数,可以用来封装代码块。 [self testBlockAsParam:^{ NSLog(@"block作为testBlockAsParam的参数"); }]; //5、block作为属性 [self setMyBlock:^{ NSLog(@"block作为属性"); }]; NSLog(@"%@",self.myBlock); self.myBlock();//block作为属性的调用 //6、访问外部变量 //block直接访问外部变量 默认是将其复制到其数据结构中来实现访问的,但是不能更改这变量的值,因为在block中这变量是const类型。 //对于访问用__block修饰的外部变量,block内是复制其地址实现访问的,block内可以修改变量的值。 int a = 5; __block int b = 10; NSLog(@"a = %d ,地址 = %p, b = %d,地址 = %p", a, &a, b, &b); void (^myBlock4)() = ^{ b = 15; NSLog(@"a = %d ,地址 = %p, b = %d,地址 = %p", a, &a, b, &b); }; myBlock4(); NSLog(@"a = %d ,地址 = %p, b = %d,地址 = %p", a, &a, b, &b); } - (void) testBlockAsParam: (void (^)()) block { block(); //执行block内部代码 }
运行结果:
ps:目前知道的就是这些,欢迎补充