視頻What's New in LLVM 中,從12:05的時間開始有個關於NSMutableArray可變數組屬性的使用問題。objective-c
運行後報錯圖以下:self.photos的實際類型是 __NSMutable0,也就NSArray類型。沒有addObject的方法。數組
OC是門動態型語言,在編譯階段不會作類型檢測。OC的內存管理是引用計數,在ARC環境下,屬性@property的內存管理語義關鍵字有copy,weak,strong,asssin。在編譯階段,默認狀況下編譯器會生成一個成員變量、一個setter方法、一個getter方法。而在setter方法中,會根據內存管理語義作相應的引用計數相關的操做。當使用copy修飾屬性時,在setter中實際操做是拷貝了一份不可變的類型對象。這樣的話,即便是其是可變類型,在被賦值後,咱們獲得的是倒是不可變類型的對象。安全
OC具備多態性,父類能夠指向子類。對象最終類型會在運行期根據實例化對象確認。在運行時階段其isa指向的是[NSArray Class]。那麼當向self.photos發送一個addObject消息時,self.photos對象是接收不到這個消息的。由於addObject是NSArray的子類NSMutbleArray的方法。app
屬性語義多種:ide
在此狀況下,實際編譯器添加setter方法以下:性能
// ARC
- (void)setPhotos:(NSMutableArray<UIImage *> *)photos{
// 1. 開始加鎖,非天然語言,這裏不寫代碼了
_photos = [photos copy];
// 2. 加鎖結束
}
複製代碼
那麼獲得的是個self.photos實際是NSArray類。atom
從上就發現了2個問題:屬性就是使用了關鍵字atomic、copy修飾。那麼這裏會加鎖而且獲得NSArray類的self.photos。spa
相關概念:線程
- 自旋鎖:當上一個線程的任務沒有執行完畢的時候(被鎖住),那麼下一個線程會一直等待(不會睡眠),當上一個線程的任務執行完畢,下一個線程會當即執行。
- 自旋鎖應用場景: 比較適合作一些不耗時的操做
一、修改copy語義在setter中默認內容:code
方式一: 手動重寫setter方法,使用賦值前mutableCopy。以下,這樣獲取到的就是NSMutableArray類型的對象。
- (void)setPhotos:(NSMutableArray<UIImage *> *)photos{
_photos = [photos mutableCopy];
}
複製代碼
方式二: 使用關鍵字strong
修飾屬性。咱們獲得的依然是可變類型。
- (void)setPhotos:(NSMutableArray<UIImage *> *)photos{
_photos = photos;
}
複製代碼
二、原子性修改: 使用:nonatomic,減小小型設備中性能消耗。