[读书笔记]iOS与OS X多线程和内存管理 [Blocks部分-4]
__block变量存储域
|
影响
|
栈
|
从栈复制到堆并被Block持有
|
堆
|
被Block持有
|
typedef
void (^aBlock)(
id);
aBlock ablock; { id array=[[NSMutableArrayalloc]init]; ablock=^(id objct){ [array addObject:objct]; NSLog(@"array count %d",[arraycount]); }; } ablock([[NSObjectalloc]init]); ablock([[NSObjectalloc]init]);
|
- 调用Block的copy实例方法
- Block作为函数返回值
- 将Block赋值给附有__strong修饰符id类型的类或Block类型成员变量时
- 在方法名含有usingBlock的Cocoa框架方法或Grand Central Dispatch的API中传递Block时。
- Block作为函数值返回时
- 将Block赋值给附有__strong修饰符id类型的类或Block类型成员变量时
- 在方法名含有usingBlock的Cocoa框架方法或Grand Central Dispatch的API中传递Block时。
Person.m文件代码
主程序代码:
{
...
Person *per=[[Personalloc]init];
NSLog(@"o");
...
}
|
-(id)init{
self=[superinit]; id __weak tmp=self; blk_=^{ NSLog(@"self %@",tmp); }; return self; }
|
//arc打开状态
@interface Person(){ void(^blk_)(void); id obj; } @end @implementation Person -(void)dealloc{ NSLog(@"person dealloc"); } -(id)init{ self=[superinit]; blk_=^{ NSLog(@"obj %@",obj); }; return self; }
|
//arc打开状态
@interface Person(){ void(^blk_)(void); } @end @implementation Person -(void)dealloc{ NSLog(@"person dealloc"); } -(id)init{ self=[superinit]; __block id tmp=self; blk_=^{ NSLog(@"obj %@",tmp); tmp=nil; } ; return self; } -(void)execBlock{ blk_(); } |
该代码没有引起循环引用,但是如果不调用execBlock这个方法,即不执行对tmp的赋值,就会引起循环引用。
通过执行execBlock,__block变量tmp对Person类对象的强引用失效。
|
- 通过__block变量可控制对象的持有时间
- 在不能使用__weak修饰符的环境下代替__unsafe_unretained修饰符,不必担心悬垂指针。
ARC无效时,需要手动将Block从栈复制到堆,用copy方法来复制,release方法来释放。只要Block位于堆上,则可以通过retain方法持有,对于栈上的Block调用retain方法不起任何作用。在c语言中也可以使Block,此时使用Block_copy和Block_release代替copy/release实例方法。另外,ARC无效时,__block说明符被用来避免Block循环引用,这是因为Block从栈复制到堆时,若Block使用的变量为附有__block说明符的id类型对象或对象类型自动变量,不会被retain,反之如果没有__block说明符则会被retain。
Block部分到此结束。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。