一、Block的简单介绍
Block 就是匿名函数 它是封装了一个代码块,这个代码块在什么时候都可以执行;
使用Block的步骤就三步:
1、定义Block变量
2、创建Block的代码块
3、调用Block
(1)无参无返回值
void (^one) = ^{ NSLog(@"hello world!"); };调用 one();
(2)无参有返回值
int (^tow) = ^{ return 1; };调用int a = tow();
(3)有参无返回值
void (^three)(int) = ^(int a){ NSLog(@"hello world!"); };调用int b = 2;three(b);
(4)有参有返回值
int (^four)(int,int) = ^(int a,int b){ return a + b;); };调用 int a = 1; int b = 2;
int sum = four (a , b);
定义Block的另一种方式 一般用 typedef void (^BlockName)( );
二、Block的注意事项
typedef void (^BlockName)( );
1.调用Block的时候首先要判空if (self.BlockName){ 在这里调用Block:self.BlockName( ) };
2.Block可以访问局部变量,但是不能修改它的值;如果要修改的话该变量必须用__block修饰;
int a = 10; void(^BlockName)() = ^{a++;}; 此处a的值不能修改
原因:此处不能修改的原因是在编译期间确定的,编译器编译的时候把a的值复制到block作为一个新变量(假设是a‘ = 10),此时a'和a是没有关系的
3.如果block块里边有self这样的代码, self必须用__weak 修饰;
__self ViewController *controller = self;
void(^BlockName)() = ^{NSLog(@"%@", controller.string); };
原因:block会对内部的对象进行一次retain,也就是说self会被retain一次。当self释放的时候,需要block释放后才会对self进行释放,但是block的释放又需要等self的dealloc中才会释放。如此一来变形成了循环引用,导致内存泄露。(一句话防止循环引用)
4.在申明block属性的时候用copy 后者strong修饰;
因为默认情况下,block是存档在栈中,可能被随时回收,需要copy到堆区一份,防止被释放掉;
@property(copy,nonatomic)BlockNamemyBlock;
5、在多线程环境下(block中的weakSelf有可能被析构的情况下),需要先将self转为strong指针,避免在运行到某个关键步骤时self对象被析构。
__weak __typeof(self)weakSelf =self;
AFNetworkReachabilityStatusBlock callback= ^(AFNetworkReachabilityStatus status) {
__strong __typeof(weakSelf)strongSelf=weakSelf;
strongSelf.networkReachabilityStatus=status;if(strongSelf.networkReachabilityStatusBlock) {
strongSelf.networkReachabilityStatusBlock(status);
}
};
第四、五、六行,如果不转成strongSelf而使用weakSelf,后面几句话中,有可能在第四句执行之后self的对象可能被析构掉,然后后面的StausBlock没有执行,导致逻辑错误。
这里边的typeof(self) 指的是任意类型
三、Block的使用
Block的使用我就简单说几点应用场景,第一点 他可以传递参数,具体来说就是实现两个ViewController之间值的传递;
第二点 他可以代替代理来使用;
第三点 他可以作为变量来传值,一般在网络请求的时候用的比较多;
.h中声明block,确定block的返回值类型和方法名和传入参数的类型
.m中block方法的实现,这里需要判断block是否为空
在另一个页面.m中调用bolock
网友评论