标题:
Blocks笔记(4)
[打印本页]
作者:
look_w
时间:
2019-2-19 15:46
标题:
Blocks笔记(4)
堆上的block
上述代码若是把数组中的block copy到堆上,即把getBlockArrayFromStack替换为下面方法,那么注释代码打开与否都无影响,原因在于copy到堆上后block仍能脱离作用域继续存在,并指向堆上的block;
-(NSArray *)getBlockArrayFromHeap {
NSArray *blockArray = [[NSArray alloc]initWithObjects:[^{NSLog(@"block-1");} copy],
[^{NSLog(@"block-2");} copy],
[^{NSLog(@"block-3");} copy],nil];
return blockArray;
}
__block变量
__block 说明符可以修饰任何类型的自动变量, __block修饰的变量其实也是block是一种结构体,初始化结构体的时候会把变量赋值给结构体的同名成员变量,若是变量是对象则会持有它,访问变量的时候则通过它的成员变量__forwarding来访问,结构如下:
struct __Block_byref_obj_0
{
void *__isa;
__Block_byref_obj_0 *__forwarding;
int __flags;
int __size;
void (*__Block_byref_id_object_copy)(void*, void*);
void (*__Block_byref_id_object_dispose)(void*);
__strong id obj;
};
static void __Block_byref_id_object_copy_131(void *dst, void *src)
{
_Block_object_assign((char*)dst + 40, *(void * *) ((char*)src + 40), 131);
}
static void __Block_byref_id_object_dispose_131(void *src)
{
_Block_object_dispose(*(void * *) ((char*)src + 40), 131);
}
/* __block variable declaration */
__Block_byref_obj_0 obj = { 0,
&obj,
0x2000000,
sizeof(__Block_byref_obj_0),
__Block_byref_id_object_copy_131,
__Block_byref_id_object_dispose_131,
[[NSObject alloc] init]
};
当block从栈copy到堆时,__block变量也会一同拷贝到堆上并被该block持有;若干个block引用同一个 __block变量,会增加该block的引用计数,当block废弃时,_block会被释放,若它引用计数为0了就会被废弃,同oc的引用计数内存管理完全一样;
无论是在block语法中,block语法外使用__block变量,还是__block变量配置在栈上或堆上,都可以顺利访问到同一个__block变量,访问形式均可转换为: ++(val.__forwarding->val),原因是: 栈上的__block用结构体实例在__block变量复制到堆上,都会将结构体(__block)的成员变量__forwarding的值替换为复制到堆上__block变量用结构体实例的地址,具体见下面例子:
- (IBAction)test_1
id)sender {
__block int val = 0;
void (^block)(void) = [^{val++;} copy];
val++;
block();
NSLog(@"%d",val);
}
打印结果: 2
---------------------
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0