1. Block的声明和线程安全

Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC下返回Block)。

另一个需要注意的问题是关于线程安全,在声明Block属性时需要确认“在调用Block时另一个线程有没有可能去修改Block?”这个问题,如果确定不会有这种情况发生的话,那么Block属性声明可以用nonatomic。如果不肯定的话(通常情况是这样的),那么你首先需要声明Block属性为atomic,也就是先保证变量的原子性(Objective-C并没有强制规定指针读写的原子性,C#有)。

比如这样一个Block类型:

typedef void (^MyBlockType)(int);

属性声明:

@property (copy) MyBlockType myBlock;

这里ARC和非ARC声明都是一样的,当然注意在非ARC下要release Block。

但是,有了atomic来保证基本的原子性还是没有达到线程安全的,接着在调用时需要把Block先赋值给本地变量,以防止Block突然改变。因为如果不这样的话,即便是先判断了Block属性不为空,在调用之前,一旦另一个线程把Block属性设空了,程序就会crash,如下代码:

if (self.myBlock)
{
//此时,走到这里,self.myBlock可能被另一个线程改为空,造成crash
//注意:atomic只会确保myBlock的原子性,这种操作本身还是非线程安全的
self.myBlock(123);
}

所以正确的代码是(ARC):

MyBlockType block = self.myBlock;
//block现在是本地不可变的
if (block)
{
block(123);
}

在非ARC下则需要手动retain一下,否则如果属性被置空,本地变量就成了野指针了,如下代码:

//非ARC
MyBlockType block = [self.myBlock retain];
if (block)
{
block(123);
}
[block release];

返回目录

2. 循环引用问题

循环引用是另一个使用Block时常见的问题。

在ARC下,由于__block抓取的变量一样会被Block retain,所以必须用弱引用才可以解决循环引用问题,iOS 5之后可以直接使用__weak,之前则只能使用__unsafe_unretained了,__unsafe_unretained缺点是指针释放后自己不会置空。示例代码:

//iOS 5之前可以用__unsafe_unretained
//__unsafe_unretained typeof(self) weakSelf = self;
__weak typeof(self) weakSelf = self;
self.myBlock = ^(int paramInt)
{
//使用weakSelf访问self成员
[weakSelf anotherFunc];
};

在非ARC下,显然无法使用弱引用,这里就可以直接使用__block来修饰变量,它不会被Block所retain的,参考代码:

//非ARC
__block typeof(self) weakSelf = self;
self.myBlock = ^(int paramInt)
{
//使用weakSelf访问self成员
[weakSelf anotherFunc];
};

iOS: ARC和非ARC下使用Block属性的问题的更多相关文章

  1. IOS开发 ARC和非ARC下使用Block属性的问题

    1. Block的声明和线程安全 Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非AR ...

  2. ios工程中ARC与非ARC的混合

    ARC与非ARC在一个项目中同时使用, 1,选择项目中的Targets,选中你所要操作的Target,2,选Build Phases,在其中Complie Sources中选择需要ARC的文件双击,并 ...

  3. (转)iOS 开发,工程中混合使用 ARC 和非ARC

    [前提知识] ARC:Automatic Reference Counting,自动引用计数 在开发 iOS 3 以及之前的版本的项目时我们要自己负责使用引用计数来管理内存,比如要手动 retain. ...

  4. IOS ARC和非ARC文件混用

    ARC在SDK4.0的时候增加的,因为要和曾经的项目融合,就会有arc和非arc文件的混合. 当然,也就这两种情况: 1.自己的旧项目没有使用ARC,可是引入的第三方库却是使用了ARC的. 2.自己的 ...

  5. iOS 开发,工程中混合使用 ARC 和非ARC(转)

    [前提知识] ARC:Automatic Reference Counting,自动引用计数 在开发 iOS 3 以及之前的版本的项目时我们要自己负责使用引用计数来管理内存,比如要手动 retain. ...

  6. iOS arc和非arc 适用 宏

    iOS arc和非arc 适用 宏 1:使用宏 + (void)showAlertWithMessage:(NSString *)messages { dispatch_async(dispatch_ ...

  7. iOS 开发,混合使用 ARC 和非ARC

    [前提知识] ARC:Automatic Reference Counting,自动引用计数 在开发 iOS 3 以及之前的版本的项目时我们要自己负责使用引用计数来管理内存,比如要手动 retain. ...

  8. iOS中ARC和非ARC混用

    如果在使用第三方类库的时候,我们可能会遇到一些内存管理的问题   那么如何在一个工程中实现ARC和非ARC混用呢,例如你创建一个ARC的工程,但是你引用的第三方类库是非ARC管理内存的   首先点击工 ...

  9. ARC 与非 ARC 之间那些的'祸害'

    你是否也曾被 assign.retain.copy.release.autorelease.strong.__strong.weak.__weak.__unsafe__unretain.__autor ...

随机推荐

  1. 看文档要看仔细,英语要加强啊... cocos2d-x 的 API 和 对应版本的 cocos2d-js 的 API 没有完全对应

    /** * Sets the X rotation (angle) of the node in degrees which performs a horizontal rotational skew ...

  2. HeadFirst设计模式之状态模式

    一. 1. 2.The State Pattern allows an object to alter its behavior when its internal state changes. Th ...

  3. 这些废弃的 HTML 标签不要用

    HTML 已经发展了多年,现在 W3C 已经发布了 HTML 5.1 的提案推荐标准,一些陈旧废弃的标签已经在后继的标准中逐渐消失.这里为大家列出那些已经被废弃 HTML 标签,看看你是不是还在使用它 ...

  4. Android:常见错误提示

    记录开发中常出现的错误 1.遇到这样的错误时,应该立马想到是书写错误或语法错误,常见为android:name写成了name Attribute is missing the Android name ...

  5. 转:C语言宏定义时#(井号)和##(双井号)的用法

    转自:http://www.cnblogs.com/welkinwalker/archive/2012/03/30/2424844.html#2678295 #在英语里面叫做 pound 在C语言的宏 ...

  6. 【算法】 输入n 输出一个n*n的zigzag矩阵 利用c++实现

    int main() { int N; cin>>N; int **a = new int *[N]; ) ;//如果没有申请到空间 ;i<N;i++) { a[i]= new in ...

  7. 通过 PHP 判断用户的设备是否是移动设备

    <?php function isMobile() { // 如果有HTTP_X_WAP_PROFILE则一定是移动设备 if (isset ($_SERVER['HTTP_X_WAP_PROF ...

  8. Maximum Allowed Error 7 错误解决

    http://blog.csdn.net/lyx123/article/details/6238167 这段时间,一直在做WINCE 的应用,后来将NK做大后,必须修改EBOOT,以便能够提供较大的空 ...

  9. grunt安装中的cli和--save-dev解释

    grunt官网安装grunt的介绍中是这么写的: npm install -g grunt-cli 这里安装Grunt的命令行支持(command line interface,简称CLI),在这之后 ...

  10. JAVA高级特性 - 注解

    注解是插入到代码中用于某种工具处理的标签.这些标签可以在源码层次上进行操作,或者可以处理编译器将其纳入到注解类文件中. 注解不会改变对程序的编译方式.Java编译器会对包含注解和不包含注解的代码生成相 ...