聲明屬性時用strong或者retain效果是同樣的(貌似更多開發者更傾向於用strong)。不過在聲明Block時,使用strong和retain會有大相徑庭的效果。strong會等於copy,而retain居然等於assign!函數
固然定義Block仍是應該用copy(還有其餘須要注意的地方,能夠參考這篇文章:iOS: ARC和非ARC下使用Block屬性的問題),由於非ARC下不copy的Block會在棧中,ARC中的Block都會在堆上的。工具
能夠這樣復現問題。在非ARC環境下,定義一個簡單類型,定義一個Block屬性,先用正確的copy:post
@interface TestCls : NSObject @property (nonatomic, copy) void(^myBlock)(); @end
在另外一個類型裏聲明變量:測試
TestCls *_testObj
而後在一個方法裏,好比viewDidLoad中,設置Block變量,注意即使是在非ARC下,沒有引用外部變量的Block類型也是NSGlobalBlock,而引用外部變量的Block纔是NSStackBlock,以下代碼atom
_testObj = [[TestCls alloc] init]; int outerVar = 12; _testObj.myBlock = ^void() { NSLog(@"Block被調用:%d", outerVar); }; NSLog(@"Block類型:%@", [_testObj.myBlock class]);
而後在另外一個方法裏(好比UIButton的點擊事件方法裏)去執行Block,以下:spa
_testObj.myBlock();
測試環境是Xcode 6/iOS 7/8,若是最上面myBlock屬性聲明是copy或者strong的話,Block都會被copy,輸出:code
Block類型:__NSMallocBlock__ Block被調用:12
若是上面myBlock屬性聲明是retain或者assign的話,Block表現起來就是assign,沒有去copy,輸出blog
Block類型:__NSStackBlock__
此時可能會Crash(BAD_ACCESS),也有可能輸出錯誤的值(我在控制檯下測試會出現這種狀況)。由於Block做用域在函數棧裏,而函數已經執行完畢了。事件
總之,strong和retain居然有不同的地方,而聲明Block屬性請務必用copy。作用域
Related posts:
iOS: 非ARC下返回Block iOS: ARC和非ARC下使用Block屬性的問題 iOS: NSData/NSMutableData的二進制數據讀寫 在線工具: 從Objective-C .m文件中提取函數定義