前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ARC无效时block的赋值

ARC无效时block的赋值

作者头像
forrestlin
发布2018-05-24 11:03:25
7760
发布2018-05-24 11:03:25
举报
文章被收录于专栏:蜉蝣禅修之道蜉蝣禅修之道

总所周知,当ARC无效时,block默认是在栈区或全局数据区,要想复制到堆区,需要一些特殊手段,这些手段在《Objective-C高级编程》都有介绍,例如将block声明为类的属性,block调用copy方法,作为函数返回值等等。

但是《高级编程》里有个地方写错了,不过也有可能书上没写清楚是否开启ARC,不过通过我的实验验证,当ARC关闭时,在类方法中给block属性赋值,如果不加上copy,还是在栈上,但是在对象外部赋值却是在堆上。具体过程看下面代码:

代码语言:javascript
复制
#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
代码语言:javascript
复制
#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,正确的赋值方式如下:

代码语言:javascript
复制
    MyObject* obj=[[MyObject alloc] init];
    int a=0;
//    [obj setInnerBlock];
    obj.blk=^(){
        NSLog(@"Block被调用:%d",a);
    };
    obj.blk();
    NSLog(@"Block类型:%@",[obj.blk class]);

希望对大家有所帮助

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年04月15日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档