block深入浅出

typedef void (^Callback)(id result);
- (void)viewDidLoad {
[self callbackDosomething:^(id result) {
NSLog(@"%@",result);
}];

}

- (void)callbackDosomething:(Callback)callback{
callback = [self callbackReDosomething:callback];
}

- (Callback)callbackReDosomething:(Callback)callback{
if (callback) {
callback(@"dosomething");
}
return callback;
}
此处的callback就是用来传递的,在另一个方法里面才callback回调

block是OC对闭包实现的一个对象,为什么说block是对象了,因为在block的数据结构中存在isa指针

1、block分为三种:NSConcreteGlobalBlock、NSConcreteStackBlock、NSConcreteMallocBlock。

第一种block是全局block,如果一个block没有引入外部变量,那么这个block就是全局block,全局block在编译时期就已经确定大小了,如同宏一样;
第二种block是栈block,当引入了外部变量时,这种block就是栈block了,NSConcreteStackBlock内部会有一个结构体__main_block_impl_0,这个结构体会保存外部变量,使其体积变大。而这就导致了NSConcreteStackBlock并不像宏一样,而是一个动态的对象。而它由于没有被持有,所以在它的内部,它也不会持有其外部引用的对象。(注意,栈block是不会持有外部变量的)
第三种block是堆block,堆block就是一个block被copy到堆上,堆block会持有外部引用对象,所以会导致可能的对象延迟释放,或者循环引用的问题。(在MRC下,局部变量如果没有用_block,在block中会对其进行copy操作,而用了_block则只会引用其地址,这也就是为什么改变局部变量需要用_block修饰了)

注意:在MRC和ARC下block的区别
将block作为实例的属性变量时,MRC下需要手动copy到堆中,也就是栈block–>堆block(如果不copy就是栈block,栈block不会持有对象),而在ARC中属性赋值默认是strong,到了block自然就变成了copy,所以在ARC下默认是堆block。

block 的生命周期:
(特别注意:堆block会持有对象,这样就导致,如果堆block不释放的话,其持有的对象也不会释放,这样就会导致循环引用或者延迟释放,所以一般的做法是_weak(ARC)或_block(MRC))

宏:
·#define weak(obj) __weak typeof(obj) weak##obj = obj

    原文作者:elliotsomething
    原文地址: https://segmentfault.com/a/1190000005038340
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞