iOS: 属性声明strong和retain竟然不一样
2016-05-06 10:13
501 查看
https://www.mgenware.com/blog/?p=2121
今天和同事在处理一处用
当然定义Block还是应该用
ARC和非ARC下使用Block属性的问题),因为非ARC下不
可以这样复现问题。在非ARC环境下,定义一个简单类型,定义一个Block属性,先用正确的
在另一个类型里声明变量:
然后在一个方法里,比如
然后在另一个方法里(比如UIButton的点击事件方法里)去执行Block,如下:
测试环境是Xcode 6/iOS 7/8,如果最上面
如果上面
此时可能会Crash(
总之,
今天和同事在处理一处用
strong声明的Block属性引发的问题时偶然发现的。在诸多教程中都会讲到:声明属性时用
strong或者
retain效果是一样的(貌似更多开发者更倾向于用
strong)。不过在声明Block时,使用
strong和
retain会有截然不同的效果。
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作用域在函数栈里,而函数已经执行完毕了。
总之,
strong和
retain竟然有不一样的地方,而声明Block属性请务必用
copy。
相关文章推荐
- 通知机制(NSNotification)
- iOS--- 文件路径保存
- iOS多线程(3)GCD
- iOS - 功能模块 - 发布时间
- iOS 键盘遮挡
- IOS SRWebSocket的使用
- iOS单个ViewController支持横屏,其他全竖屏方法
- iOS多线程中performSelector: 和dispatch_time的不同
- IOS开发中,TextField和TextView有何区别
- iOS开发-进阶:被误解的MVC和被神化的MVVM(作者:唐巧)
- IOS项目代码行统计
- 【代码笔记】iOS-判断字符串是否为空
- iOS 测试三方 KIF 的那些事
- iOS开发-Xcode 调试技巧(很常用)
- iOS多线程(2)基本使用
- 《Motion Design for iOS》(十二)
- iOS数据持久化
- iOS动态性runtime初探(改私有变量,私有方法)
- iOS ---- KVO的内部实现原理
- iOS tabelView获取当前选中cell