1. 为什么要使用block。
我们知道,对象与对象之间的通信方式有以下三种:1、代理-协议;2、通知;3、block。三种方式都实现了对象之间的解耦合。其中不同就是:通知的通信方式是1对多;代理、block的通信方式是1对1.
2.Block的简介。
- Block是iOS4.0之后新增的一种语法结构,也成为“闭包”。
- SDK4.0新增的API大量使用了block
- Block是一个匿名的函数代码块,此代码块可以作为参数传递给其他对象。
3. Block的使用
//int 是返回值;sumBlock 是Block变量类型;(int x,int y)括号里面是参数。 int(^sumBlock)(int x,int y);
1 //创建 myBlock 2 - (void)createMyBlock { 3 //定义block变量 4 int(^sumBlock)(int x,int y); 5 //实现block,并且赋值 6 sumBlock = ^(int x,int y){ 7 return x + y; 8 }; 9 //声明myBlock变量,全局{int(^myBlock)(int x,int y);}
10 myBlock = sumBlock; 11 NSLog(@"%d",myBlock(20,20)); 12 }
4. 创建Block
Block有以下4种方式:
1 //Block是匿名函数,无法通过函数名调用,所以单独使用没有意义 2 // 1.无参数 无返回值--与直接打印数据是一样的效果,无意义 3 ^(){ 4 NSLog(@"无参数 无返回值"); 5 }(); 6 7 // 2.有参数 无返回值 8 ^(int a,NSString* text){ 9 NSLog(@"%d %@",a,text); 10 }(10,@"有参数 无返回值"); 11 12 // 3.有返回值 无参数 13 NSString* a = ^(){ 14 return @"无参数 有返回值"; 15 }(); 16 NSLog(@"%@",a); 17 18 // 4.有参数 有返回值 19 //定义block变量 20 int(^sumBlock)(int x,int y); 21 //实现block,并且赋值 22 sumBlock = ^(int x,int y){ 23 return x + y; 24 }; 25 NSLog(@"%d",sumBlock(10,10)); 26 }
1 //有参数 有返回值(返回结果是 6 ) 2 int(^powefBlock)(int x,int y); 3 powefBlock = ^(int x,int y){ 4 return x * y; 5 }; 6 NSLog(@" powef = %d",powefBlock(2,3));
5. Block和变量
- 变量按作用可以分为全局变量和局部变量。
- block中可以使用这两种变量,但是有不同的管理机制。
引用局部变量
- block引用局部变量时候,改变量会作为常量编码到block块中。
- 局部变量需要使用__block修饰,才能在block中修改。
1 // 如果在block 代码内部,使用外部变量时,number会变为常量 2 int number = 10; 3 ^(){ 4 //number = 20; 直接报错 ---不可以修改,已经变为常量 5 NSLog(@"%d",number); 6 }(); 7 8 //--在内部改变- 9 //在变量前加__block 声明即可 10 __block int number_1 = 10; 11 ^(){ 12 number_1 = 20; 13 NSLog(@"%d",number_1); 14 }();
- 引用外部变量
#import <Foundation/Foundation.h> @interface MyObject : NSObject { //block 引用外部 成员变量 int _number; } - (void)log; @end
1 - (void)log { 2 3 // block 引用外部 成员变量 4 _number = 99; 5 NSLog(@"---%ld-- ",self.retainCount); 6 // 使用block 修饰obj 对象 这样obj 在block中使用不会被retain。 7 // obj 不能拥有 self 的所有权 block不会持有self对象 8 __block MyObject* obj = self; 9 ^(){ 10 // 判断 obj 是否存在 11 if (!obj) { 12 return ; 13 } 14 //通过obj 获取成员变量;打印结果是 1 15 int a = obj -> _number; 16 NSLog(@"---%d-- ",a); 17 NSLog(@"*****%ld**** ",self.retainCount); 18 }(); 19 20 }
6. Block的内存管理
- 在block里面引用一个局部的Objective-C对象的时候,该对象会被retain。
- 如果局部变量使用__block修饰,则不会被retain。
1 //--------引用外部obj对象的时候---------- 2 //不会被retain,即obj1.retainCount始终是1 3 //__block NSObject* obj1 = [[NSObject alloc] init]; 4 //延时调用以后,obj1.retainCount会变为2 5 NSObject* obj1 = [[NSObject alloc] init]; 6 NSLog(@"%ld",obj1.retainCount); 7 8 //延时调用 9 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 10 NSLog(@"%ld",obj1.retainCount); 11 });
- block本身可以像对象一样copy和release
- block创建后内存是分配在栈上,调用copy方法之后,将block移动到堆中。
- 当block声明为全局变量时候,应该调用block的copy方法。
7. 循环引用
- 在block(点语法)里面引用一个实例变量的时候,改实例变量会被retain。
- 如上规则容易导致循环引用,造成内
欢迎读者查阅,如若转载,请标明出处。