iOS: 属性声明strong和retain竟然不一样
今天和同事在處理一處用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:
1 @interface TestCls : NSObject 2 3 @property (nonatomic, copy) void(^myBlock)(); 4 5 @end?
在另一個類型里聲明變量:
?1 TestCls *_testObj?然后在一個方法里,比如viewDidLoad中,設置Block變量,注意即便是在非ARC下,沒有引用外部變量的Block類型也是__NSGlobalBlock__,而引用外部變量的Block才是__NSStackBlock__,如下代碼:
1 _testObj = [[TestCls alloc] init]; 2 3 int outerVar = 12; 4 5 _testObj.myBlock = ^void() 6 { 7 NSLog(@"Block被調用:%d", outerVar); 8 }; 9 NSLog(@"Block類型:%@", [_testObj.myBlock class]);然后在另一個方法里(比如UIButton的點擊事件方法里)去執行Block,如下:
?1 _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。
?
轉載于:https://www.cnblogs.com/fengmin/p/5390073.html
總結
以上是生活随笔為你收集整理的iOS: 属性声明strong和retain竟然不一样的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SonarQube代码扫描工具
- 下一篇: 方便自己的换算器