ARC无效时block的赋值
2016-04-15 21:17
330 查看
总所周知,当ARC无效时,block默认是在栈区或全局数据区,要想复制到堆区,需要一些特殊手段,这些手段在《Objective-C高级编程》都有介绍,例如将block声明为类的属性,block调用copy方法,作为函数返回值等等。
但是《高级编程》里有个地方写错了,不过也有可能书上没写清楚是否开启ARC,不过通过我的实验验证,当ARC关闭时,在类方法中给block属性赋值,如果不加上copy,还是在栈上,但是在对象外部赋值却是在堆上。具体过程看下面代码:
#import <Foundation/Foundation.h>
typedef void(^blk_t)();
@interface MyObject : NSObject
@property(nonatomic,copy) blk_t blk;
@property(nonatomic,retain)NSString* name;
-(void)setInnerBlock;
@end
#import "MyObject.h"
@interface MyObject(){
int _index;
}
@end
@implementation MyObject
void retainCount(NSObject* __unsafe_unretained obj){
NSLog(@"the retain count is:%ld",CFGetRetainCount((__bridge CFTypeRef)obj));
}
-(instancetype)init{
self=[super init];
if(self){
// typeof(self) __block wself=self;
retainCount(self);
}
return self;
}
-(void)setInnerBlock{
_blk=^(){
self->_index=10;
};
}
@end
此时如果定义一个MyObject对象,调用setInnerBlock后,再调用_blk,将会报出BAD_ADDRESS错误,因为栈上的block已经被销毁,blk这时是野指针。要是查看blk的class也是stackblock,正确的赋值方式如下:
MyObject* obj=[[MyObject alloc] init];
int a=0;
// [obj setInnerBlock];
obj.blk=^(){
NSLog(@"Block被调用:%d",a);
};
obj.blk();
NSLog(@"Block类型:%@",[obj.blk class]);
希望对大家有所帮助
但是《高级编程》里有个地方写错了,不过也有可能书上没写清楚是否开启ARC,不过通过我的实验验证,当ARC关闭时,在类方法中给block属性赋值,如果不加上copy,还是在栈上,但是在对象外部赋值却是在堆上。具体过程看下面代码:
#import <Foundation/Foundation.h>
typedef void(^blk_t)();
@interface MyObject : NSObject
@property(nonatomic,copy) blk_t blk;
@property(nonatomic,retain)NSString* name;
-(void)setInnerBlock;
@end
#import "MyObject.h"
@interface MyObject(){
int _index;
}
@end
@implementation MyObject
void retainCount(NSObject* __unsafe_unretained obj){
NSLog(@"the retain count is:%ld",CFGetRetainCount((__bridge CFTypeRef)obj));
}
-(instancetype)init{
self=[super init];
if(self){
// typeof(self) __block wself=self;
retainCount(self);
}
return self;
}
-(void)setInnerBlock{
_blk=^(){
self->_index=10;
};
}
@end
此时如果定义一个MyObject对象,调用setInnerBlock后,再调用_blk,将会报出BAD_ADDRESS错误,因为栈上的block已经被销毁,blk这时是野指针。要是查看blk的class也是stackblock,正确的赋值方式如下:
MyObject* obj=[[MyObject alloc] init];
int a=0;
// [obj setInnerBlock];
obj.blk=^(){
NSLog(@"Block被调用:%d",a);
};
obj.blk();
NSLog(@"Block类型:%@",[obj.blk class]);
希望对大家有所帮助
相关文章推荐
- 汉诺塔问题递归解法
- CSS3 @keyframes 规则
- Android(三)----数据存储和界面展现02
- Android:利用SharedPreferences实现自动登录
- Program2_1011
- 3. NHibernate基础知识 - 你必须知道的一些事情
- eclipse maven 项目导出为 jar 包
- CSS 在编写时要注意的15个问题
- 数据库连接及操作
- Lightoj1393(博弈+NIM)
- JDK5新特性之增强for
- httpclient4.1使用详解
- hdu 2132... 被基本问题考住了。。
- poj3468 线段树
- NavigationDrawe 实践
- 练习二1009
- 如何使用R语言的Boruta包进行特征选择
- ACM--枚举+DFS/巧妙思想--POJ--2965--The Pilots Brothers' refrigerator--初期算法
- VS2012——由于缺少目标xx.exe,Visual Studio
- Spring项目的建立-移植流程(非入门教程)