block的类型
没有引用引用外部变量的block是全局block(NSGlobalBlock)
引用了外部变量的block在声明时(执行代码是在栈内存),处于栈内存,所以是栈block(NSStackBlock);由于栈中对象的内存由系统管理,对象内存的回收由系统决定,所以为了防止下次调用block时block已被回收,就需要把刚声明的block(栈block)以及block中引用的对象copy到堆上,这时刚才声明的block就变成了堆block(NSMallocBlock)。
//***************** block类型 ****************
//__NSGlobalBlock__
NSLog(@"%@", ^{
});
//__NSStackBlock__
NSLog(@"%@", ^{
NSLog(@"%@", obj);
});
self.block = ^{
NSLog(@"%@", obj);
};
//__NSMallocBlock__
NSLog(@"%@", self.block);
block与引用计数
NSObject *obj = [NSObject new];
__weak NSObject *objw = obj;
NSLog(@"obj: %ld", CFGetRetainCount((__bridge CFTypeRef)(obj)));//1
NSLog(@"objw: %ld", CFGetRetainCount((__bridge CFTypeRef)(objw)));//2 __weak修饰的对象不会增加原对象的引用计数,__weak对象的引用计数只是返回原对象retainCount + 1
//引用__weak修饰的对象
^{
NSLog(@"objw: %ld", CFGetRetainCount((__bridge CFTypeRef)(objw)));//2 未增加
}();
//引用__weak修饰的对象
^{
NSLog(@"objw: %ld", CFGetRetainCount((__bridge CFTypeRef)(objw)));//2 未增加
}();
//引用 非 __weak修饰的对象
^{
NSLog(@"obj: %ld", CFGetRetainCount((__bridge CFTypeRef)(obj)));//2 增加1
}();
//引用 非 __weak修饰的对象
^{
NSLog(@"obj: %ld", CFGetRetainCount((__bridge CFTypeRef)(obj)));//3 增加1
}();
//用__strong修饰的对象
^{
NSLog(@"obj: %ld", CFGetRetainCount((__bridge CFTypeRef)(obj)));//4
__strong Obj *objs = objw;
NSLog(@"obj: %ld", CFGetRetainCount((__bridge CFTypeRef)(objw)));//6
NSLog(@"obj: %ld", CFGetRetainCount((__bridge CFTypeRef)(objs)));//5
NSLog(@"obj: %ld", CFGetRetainCount((__bridge CFTypeRef)(obj)));//5
}();
结论:block内部不会对自己所引用的__weak的变量(objw)增加引用计数,__strong修饰的(__objs)外部的__weak变量(__objw)会增加原变量(__obj)的引用计数,但是block执行完之后__strong修饰的变量引用计数为减1。