总的来说,这和 __block 这个关键字有关系。
这里有种细节可以说明下:
1. id obj; 实际上是:__strong id obj; 这里 obj 会有__strong 修饰符号;
2. 任何有__strong 或者是有__block 或者两种修饰符同时有的变量,在转换成 block 对象时,也就是转换成底层对象时候,会额外生成两个函数,一个叫__main_block_copy_0(它底层会调用_Block_object_assign),另一个叫__main_block_dispose_0(它底层会调用_Block_object_dispose)。这两个函数在栈拷贝 block 入堆 以及 从堆上释放内存块的时候调用。
3. 你用__block 或者__strong 修饰变量,这两种情况,被修饰的对象,都会在函数 block 被生成的时候由栈区入堆区。
4. 拷贝使用 copy ,释放使用 dispose.
最后来看你的 block 的底层实现,我们要关心两部分内容,这是第一部分:
/////////////////////////////////////////// 你看到的:
blk_ = ^{
NSLog(@"self = %@", tmp);
};
/////////////////////////////////////////// 使用 clang -rewrite-objc file.m 转换后的:
// @
implementation MyObject
struct __Block_byref_tmp_0 {
void *__isa;
__Block_byref_tmp_0 *__forwarding;
int __flags;
int __size;
void (*__Block_byref_id_object_copy)(void*, void*);
void (*__Block_byref_id_object_dispose)(void*);
id tmp;
};
第二部分:
/////////////////////////////////////////// 你看到的:
blk_();
/////////////////////////////////////////// 使用 clang -rewrite-objc file.m 转换后的:
static void __MyObject__init_block_func_0(struct __MyObject__init_block_impl_0 *__cself) {
__Block_byref_tmp_0 *tmp = __cself->tmp; // bound by ref
NSLog((NSString *)&__NSConstantStringImpl__var_folders_zg_tjgxj12j793ccbxmtsg3l_0m0000gn_T_Test_b86496_mi_0, (tmp->__forwarding->tmp));
}
看到没,两部分里面的 tmp(第一部分就是 id tmp ,第二部分是 tmp->__forwarding->tmp),和 self 没扯上关系。