Block类型
Block的三种类型:__NSGlobalBlock,__NSStackBlock,__NSMallocBlock
__NSGlobalBlock:没有引用变量或OC属性的block就是__NSGlobalBlock
__NSStackBlock:引用变量或OC属性的block就是__NSStackBlock
__NSMallocBlock:当一个__NSStackBlock调用了copy或强引用,返回的就是一个__NSMallocBlock
注:在ARC环境下,编译器会自动把栈上的block copy到堆上
拷贝block
如果原来就在堆上,就将引用计数加1
如果原来在栈上,会拷贝在堆上,引用计数初始化为1,并且会调用copy helper方法(如果存在的话)
如果block在全局区,不用加引用计数,也不用拷贝,直接返回block本身
参数arg就是block_layout对象
返回值是拷贝后的block的地址
触发拷贝时机
手动copy(MRC)
被强引用或copy修饰
系统API包含usingBlock
代码
#import "block.h"
@interface block ()
@property(nonatomic,copy)void(^block)(void);
@end
@implementation block
//编译过程
//clang
//老编译过程:语法检查->oc转换c/c++->生成中间码->llvm链接
//新编译过程:语法检查->生成中间码->llvm链接
-(void)done{
//循环引用self->block->self
//1.__weak没有引用修饰对象,把地址作为key把self作为value放在弱引用表中,当没有强引用的情况下释放为nil
__weak typeof(self) weakSelf = self;
//2.前提必须是__NSMallocBlock,__NSMallocBlock捕获了self,self被copy在堆上,再次强引用self,导致循环引用
self.block = ^(){
//3.weakSelf此时代表从弱引用表中取出的self
NSLog(@"%@",weakSelf);
//保活block,持续作用域为2秒
__strong typeof(weakSelf) strongSelf = weakSelf;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(),^{
NSLog(@"%@",strongSelf);
});
};
self.block();
}
@end