ARC无效时block的赋值

来源:互联网 发布:spark save json 编辑:程序博客网 时间:2024/05/19 00:51

总所周知,当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 MyObjectvoid 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]);
希望对大家有所帮助

0 0
原创粉丝点击