iOS: 属性声明strong和retain竟然不一样

https://www.mgenware.com/blog/?p=2121

今天和同事在处理一处用strong声明的Block属性引发的问题时偶然发现的。在诸多教程中都会讲到:声明属性时用strong或者retain效果是一样的(貌似更多开发者更倾向于用strong)。不过在声明Block时,使用strongretain会有截然不同的效果。strong会等于copy,而retain竟然等于assign

当然定义Block还是应该用copy(还有其他需要注意的地方,可以参考这篇文章:iOS: ARC和非ARC下使用Block属性的问题),因为非ARC下不copy的Block会在栈中,ARC中的Block都会在堆上的。

 

可以这样复现问题。在非ARC环境下,定义一个简单类型,定义一个Block属性,先用正确的copy

@interface TestCls : NSObject
@property (nonatomic, copy) void(^myBlock)();

@end

 

在另一个类型里声明变量:

TestCls *_testObj

 

然后在一个方法里,比如viewDidLoad中,设置Block变量,注意即便是在非ARC下,没有引用外部变量的Block类型也是__NSGlobalBlock__,而引用外部变量的Block才是__NSStackBlock__,如下代码:

_testObj = [[TestCls alloc] init];

int outerVar = 12;
_testObj.myBlock = ^void()
{
    NSLog(@"Block被调用:%d", outerVar);
};
NSLog(@"Block类型:%@", [_testObj.myBlock class]);

 

然后在另一个方法里(比如UIButton的点击事件方法里)去执行Block,如下:

_testObj.myBlock();

 

测试环境是Xcode 6/iOS 7/8,如果最上面myBlock属性声明是copy或者strong的话,Block都会被copy,输出:

Block类型:__NSMallocBlock__
Block被调用:12

 

如果上面myBlock属性声明是retain或者assign的话,Block表现起来就是assign,没有去copy,输出:

Block类型:__NSStackBlock__
此时可能会Crash( BAD_ACCESS ),也有可能输出错误的值(我在控制台下测试会出现这种情况)。因为Block作用域在函数栈里,而函数已经执行完毕了。

 

总之,strongretain竟然有不一样的地方,而声明Block属性请务必用copy


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值