标签:
转换前代码:
int
global_val=1;//全局变量
static
int static_global_val=2;//静态全局变量
int
main() {
static int
static_val=3;//静态变量
void(^testBlock)(void)=^{
static_val=4; static_global_val=5;
global_val=6;
printf("%d,%d,%d",global_val,static_global_val,static_val);
};
testBlock();
}
|
转换后部分代码:
struct
__main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc; int *static_val;//静态变量被加到结构体中 __main_block_impl_0(void*fp, struct __main_block_desc_0 *desc, int *_static_val, int flags=0) : static_val(_static_val) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; static void __main_block_func_0(struct__main_block_impl_0 *__cself) {
int *static_val = __cself->static_val;// bound by copy
(*static_val)=4;
static_global_val=5;//静态全局变量和全局变量使用和转换前一致。 global_val=6;// printf("%d,%d,%d",global_val,static_global_val,(*static_val)); }
|
原代码:
//__block修饰符
int main() { __block int val=0; void(^tetsBlock)(void)=^{val=2;}; }
|
转换之后:
struct
__Block_byref_val_0 {
void *__isa; __Block_byref_val_0 *__forwarding; int __flags; int __size; int val; };
struct
__main_block_impl_0 {
struct __block_impl impl; struct __main_block_desc_0* Desc; __Block_byref_val_0 *val; // by ref __main_block_impl_0(void*fp, struct __main_block_desc_0 *desc, __Block_byref_val_0 *_val,int flags=0) : val(_val->__forwarding) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; static void __main_block_func_0(struct__main_block_impl_0 *__cself) { __Block_byref_val_0 *val = __cself->val; // bound by ref (val->__forwarding->val)=2;} static void __main_block_copy_0(struct__main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->val, (void*)src->val,8/*BLOCK_FIELD_IS_BYREF*/);} static void __main_block_dispose_0(struct__main_block_impl_0*src) {_Block_object_dispose((void*)src->val,8/*BLOCK_FIELD_IS_BYREF*/);} static struct __main_block_desc_0 { size_t reserved; size_t Block_size; void (*copy)(struct __main_block_impl_0*, struct__main_block_impl_0*); void (*dispose)(struct __main_block_impl_0*); } __main_block_desc_0_DATA = { 0, sizeof(struct__main_block_impl_0), __main_block_copy_0, __main_block_dispose_0}; int main() { __attribute__((__blocks__(byref))) __Block_byref_val_0 val = {(void*)0,(__Block_byref_val_0 *)&val, 0,sizeof(__Block_byref_val_0),0}; void(*tetsBlock)(void)=(void(*)())&__main_block_impl_0((void*)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_val_0 *)&val,570425344); } |
struct
__Block_byref_val_0 {
void *__isa; __Block_byref_val_0 *__forwarding; int __flags; int __size; int val; };
|
static
void __main_block_func_0(struct__main_block_impl_0 *__cself) {
__Block_byref_val_0 *val = __cself->val; // bound by ref (val->__forwarding->val)=2;
}
|
|
转换前代码:
int
main() {
__block int val=0; void(^tetsBlock1)(void)=^{val=2;}; void(^testBlock2)(void)=^{val=8;}; }
|
转换后关键代码:
int
main() {
__attribute__((__blocks__(byref))) __Block_byref_val_0 val = {(void*)0,(__Block_byref_val_0 *)&val, 0,sizeof(__Block_byref_val_0),0}; void(*tetsBlock1)(void)=(void(*)())&__main_block_impl_0((void*)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_val_0 *)&val,570425344);//同时使用了val这个变量 void(*testBlock2)(void)=(void(*)())&__main_block_impl_1((void*)__main_block_func_1, &__main_block_desc_1_DATA, (__Block_byref_val_0 *)&val,570425344);// }
|
|
void(^tetsBlock1)(void)=^{};
int
main() { }
|
该Block的类:
impl.isa = &_NSConcreteGlobalBlock;
|
typedef
int (^type_block)(int);
type_block func(int rate){ return ^(int count){return rate*count;};//在非ARC环境下会报错:Returning block that lives on the local stack,在ARC下正常。 }
|
大致流程:
源码在对应的ARC编译器下转换为
使用objc_retainBlock函数处理生成的Block对象tmp_block=objc_retainBlock(tmp_block)
而objc_retainBlock实际就是_Block_copy函数,即
/** * 将通过Block语法生成的Block赋值给变量tmp_block */
// _Block_copy函数将栈上的Block复制到堆上,复制后将堆上的地址作为指针赋值给变量tmp_block;
tmp_block=_Block_copy(tmp_block);
// 将堆上的Block作为OC对象注册到autoreleasepool中并返回该对象。
return
objc_autoreleaseReturnValue(tmp_block);
|
-(id)getBlockArray{
int val=10; return [[NSArray alloc]initWithObjects:^{NSLog(@"%d",val);},^{NSLog(@"%d",val);},nil]; }
使用:
//由于getBlockArray函数执行结束,栈上的Block被废除,程序崩溃
NSArray*array= [selfgetBlockArray];
void (^aBlock)(void)=array[0];
aBlock();
|
修改后代码:
-(id)getBlockArray{
int val=8;
return [[NSArrayalloc]initWithObjects:[^{NSLog(@"%d",val);}copy],[^{NSLog(@"%d",val);}copy],nil];
}
|
Block类
|
原存储位置
|
复制效果
|
_NSConcreteStackBlock
|
栈区
|
从栈复制到堆
|
_NSConcreteGlobalBlock
|
程序的数据区域
|
无任何变化
|
_NSConcreteMallocBlock
|
堆区
|
引用计数增加
|
源代码:
typedef void
(^aBlock)(void);
aBlock
oneBlock;
oneBlock =[[[oneBlock
copy]copy]copy];
该代码可理解为:
{
aBlock tmp=[oneBlock copy]; oneBlock=tmp; } { aBlock tmp=[oneBlock copy]; oneBlock=tmp; } { aBlock tmp=[oneBlock copy]; oneBlock=tmp; }
提示:
ARC模式下赋值时系统会自动增加强引用 当对象被赋值为nil,对象相关的强引用将被销毁 |
加入注释:
oneBlock =[[[oneBlockcopy]copy]copy];
{ //将堆上的Block赋值给tmp,tmp持有强引用的Block aBlock tmp=[oneBlock copy];//执行copy后从栈到堆 //由于此时为ARC模式,赋值后oneBlock持有堆上的Block的强引用,此时Block的持有者为oneBlock和tmp。(在非ARC模式下为简单赋值,oneBlock并未持有强引用,需手动增加引用计数,否则如果tmp被释放,oneBlock将不可使用); oneBlock=tmp; }
//超出tmp变量作用域,tmp被arc自动释放,但Block仍被oneBlock引用,未被释放
{
//tmp持有堆上的Block的强引用 aBlock tmp=[oneBlock copy]; //赋值给oneBlock,oneBlock原先指向的堆上的Block强引用被释放,原先指向的堆上的Block并未废弃(tmp强引用)。oneBlock现在持有与tmp相同的强引用。现在堆上的Block被oneBlock和tmp持有。 oneBlock=tmp; } //tmp指向的强引用被销毁,堆上的Block由于被oneBlock持有,仍然存在。 //下面过程同上 { aBlock tmp=[oneBlock copy]; oneBlock=tmp; }
|
示意图:
|
[读书笔记]iOS与OS X多线程和内存管理 [Blocks部分-3]
标签:
原文地址:http://blog.csdn.net/zhaoyabei/article/details/44056123