1. 程式人生 > >關於iOS中property修飾符個人的一點理解

關於iOS中property修飾符個人的一點理解

在日常的iOS開發中,我們每天都會使用到property,但是對於property的修飾符,可能大家跟我以前一樣,理解的不是特別透徹,現在就讓我們來了解了解吧,

首先,一個property是可以看成是:

property = 例項變數+setter方法+getter方法

屬性修飾符會直接影響後續編譯器對於setter和getter方法的合成,屬性的修飾符分為以下三類:

1.原子性

atomic VS nonatomic

具備atomic特質的屬性,編譯器合成的setter和getter方法會加鎖,能夠保證當多個執行緒在讀寫屬性時,總是能夠獲取到屬性值,如果修飾符為nonatomic,則不會對setter和getter方法加鎖,在通常情況下,使用nonatomic不會帶來什麼問題,但是如果一個執行緒在多次修改某個屬性時,另一個執行緒去讀取屬性時,可能會取到未修改好的屬性,下面我們將舉例來證明:



使用nonatomic修飾dataArray,會崩潰



使用atomic修飾dataArray,不會崩潰

在這段程式碼中,我們有一個用nonatomic,strong修飾的陣列dataArray,我們在一個非同步佇列的任務中持續地去修改這個屬性,在另一個非同步佇列的任務中持續地去讀取這個屬性,由於dataArray是由strong來修飾的,那麼在dataArray的setter方法中,其實是先保留新值,後釋放舊值,再將指標指向新值,所以在後面這個非同步佇列的任務中,取到的dataArray可能是一個已經被釋放的殭屍物件,所以會崩潰。

那麼還有一個問題

atomic是執行緒安全的嗎?

讓我們先來了解一下執行緒安全的概念,

多執行緒操作共享資料不會出現想不到的結果就是執行緒安全的,否則,是執行緒不安全的。

下面讓我們來做個小實驗,


對用atomic修飾的陣列連續修改時,讀取屬性

輸出結果為:


輸出結果

我們對在一個非同步佇列的任務中,對dataArray多次寫入,並在另一個非同步佇列中多次讀取dataArray,從輸出結果中發現,得到的結果並不一樣,所以使用atomic也並不能保證執行緒安全。

2.讀/寫許可權

readwrite VS readonly

readwrite修飾的屬性只會合成setter和getter方法

readonly修飾的屬性只會合成getter方法,可以以直接訪問例項變數的方式來完成賦值操作

3.記憶體管理

這方面的修飾符主要是影響編譯器合成setter方法,

assign

主要修飾基礎型別,使用assign修飾的屬性的setter方法主要是執行簡單的賦值操作

weak

weak是ARC中新增加的屬性修飾符,主要定義一種“非擁有關係”,使用weak修飾的屬性的setter方法會既不保留新值,也不釋放舊值,不會使屬性指的物件的引用計數增加,當指向的物件被釋放時,屬性值也會被自動置為nil。

strong

strong是ARC中新增加的屬性修飾符,跟MRC時代中的retain修飾符很像,描述一種“擁有關係”,使用strong修飾的屬性的setter方法會先保留新值,再釋放舊值,最後把新值設定上。

unsafe_unretained

unsafe_unretained與assign類似,但是用於物件型別,從字面意思上,也能看到,它是不安全,也不會強引用物件,所以它跟weak很相似,跟weak的區別在於當指向的物件被釋放時,屬性不會被置為nil,所以是不安全的。

copy

copy表達的語義相似,都會持有物件,但是它的setter方法不會保留新值,而是會呼叫物件的copy方法將新值拷貝一份,然後將它設定上,所以使用copy修飾的型別必須遵NSCopying協議,實現-(void)copyWithZone:(NSZone *)zone方法。