iOS的屬性聲明:retain和strong的區別


  聲明屬性時用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。

Related posts:

iOS: 非ARC下返回Block
iOS: ARC和非ARC下使用Block屬性的問題
iOS: NSData/NSMutableData的二進制數據讀寫
在線工具: 從Objective-C .m文件中提取函數定義

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM