OC中的__block修饰符
__block修饰符
__block可以用于解决block内部无法修改auto变量值的问题, __block不能修饰全局变量、静态变量
写下面的block代码:
int main(int argc, const char * argv[]) { @autoreleasepool { __block int age = 0; void(^test)(void) = ^{ age = 10; NSLog(@"%d",age); }; test(); } return 0; }
经过xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m转为C++代码后,
关键代码如下:
static struct __test1_block_desc_0 { size_t reserved; size_t Block_size; } __test1_block_desc_0_DATA = { 0, sizeof(struct __test1_block_impl_0)}; void test1() { block = ((void (*)())&__test1_block_impl_0((void *)__test1_block_func_0, &__test1_block_desc_0_DATA)); } struct __Block_byref_age_0 { void *__isa; __Block_byref_age_0 *__forwarding; int __flags; int __size; int age; }; struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; __Block_byref_age_0 *age; // by ref __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_age_0 *_age, int flags=0) : age(_age->__forwarding) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } };
变量在被__block修饰后,会被包装成__Block_byref_变量_0的一个对象,该变量会被copy到堆上。
当block在栈上时,并不会对__block变量产生强引用
当block被copy到堆时,会调用block内部的copy。copy函数内部会调用_Block_object_assign函数
_Block_object_assign函数会对__block变量形成强引用
NSObject *object = [[NSObject alloc] init]; __block NSObject *tempObject = object; void(^test)(void) = ^{ NSLog(@"%p",tempObject);
}; test();
转为C++之后,会进行强引用:
struct __Block_byref_tempObject_0 { void *__isa; __Block_byref_tempObject_0 *__forwarding; int __flags; int __size; void (*__Block_byref_id_object_copy)(void*, void*); void (*__Block_byref_id_object_dispose)(void*); NSObject *__strong tempObject; };
进行__weak修饰之后,
NSObject *object = [[NSObject alloc] init]; __block __weak NSObject *tempObject = object; void(^test)(void) = ^{ NSLog(@"%p",tempObject); }; test();
转为C++代码:
struct __Block_byref_tempObject_0 { void *__isa; __Block_byref_tempObject_0 *__forwarding; int __flags; int __size; void (*__Block_byref_id_object_copy)(void*, void*); void (*__Block_byref_id_object_dispose)(void*); NSObject *__weak tempObject; };
当block从堆中移除时,会调用block内部的dispose函数,dispose函数内部会调用_Block_object_dispose函数
_Block_object_dispose函数会自动释放引用的__block变量(realse)