readonly: 此標記說明屬性是只讀的,預設的標記是讀寫,如果你指定了只讀,在@implementation中只需要一個讀取器。或者如果你使用@synthesize關鍵字,也是有讀取器方法被解析。而且如果你試圖使用點操作符為屬性賦值,你將得到一個編譯錯誤。 readwrite: 此標記說明屬性會 ...
readonly: 此標記說明屬性是只讀的,預設的標記是讀寫,如果你指定了只讀,在@implementation中只需要一個讀取器。或者如果你使用@synthesize關鍵字,也是有讀取器方法被解析。而且如果你試圖使用點操作符為屬性賦值,你將得到一個編譯錯誤。
readwrite: 此標記說明屬性會被當成讀寫的,這也是預設屬性。設置器和讀取器都需要在@implementation中實現。如果使用@synthesize關鍵字,讀取器和設置器都會被解析。
nonatomic: 非原子性訪問,對屬性賦值的時候不加鎖,多線程併發訪問會提高性能。如果不加此屬性,則預設是兩個訪問方法都為原子型事務訪問。
atomic 和 nonatomic 用來決定編譯器生成的 getter 和 setter 是否為原子操作。
1.atomic 設置成員變數的 @property 屬性時,預設為 atomic,提供多線程安全。
在多線程環境下,原子操作是必要的,否則有可能引起錯誤的結果。加了atomic,setter函數會變成下麵這樣:
{lock} if (property != newValue) { [property release]; property = [newValue retain]; } {unlock}
2.nonatomic 禁止多線程,變數保護,提高性能。
atomic是Objc使用的一種線程保護技術,基本上來講,是防止在寫未完成的時候被另外一個線程讀取,造成數據錯誤。而這種機制是耗費系統資源的,所以在iPhone這種小型設備上,如果沒有使用多線程間的通訊編程,那麼nonatomic是一個非常好的選擇。
指出訪問器不是原子操作,而預設地,訪問器是原子操作。這也就是說,在多線程環境下,解析的訪問器提供一個對屬性的安全訪問,從獲取器得到的返回值或者通過設置器設置的值可以一次完成,即便是別的線程也正在對其進行訪問。如果你不指定 nonatomic ,在自己管理記憶體的環境中,解析的訪問器保留並自動釋放返回的值,如果指定了 nonatomic ,那麼訪問器只是簡單地返回這個值。
assign: 簡單賦值,不更改索引計數
copy: 建立一個索引計數為1的對象,然後釋放舊對象
retain: 釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數為1
copy與retain: copy其實是建立了一個相同的對象,而retain不是: 比如一個NSString對象,地址為0×1111,內容為@”STR” ,Copy到另外一個NSString之後,地址為0×2222,內容相同,新的對象retain為1,舊有對象沒有變化, retain到另外一個NSString之後,地址相同(建立一個指針,指針拷貝),內容當然相同,這個對象的retain值+1 ,也就是說,retain是指針拷貝,copy是內容拷貝。哇,比想象的簡單多了…
assign與retain: copy其實是建立了一個相同的對象,而retain不是:
1. 接觸過C,那麼假設你用malloc分配了一塊記憶體,並且把它的地址賦值給了指針a,後來你希望指針b也共用這塊記憶體,於是你又把a賦值給(assign)了b。此時a和b指向同一塊記憶體,請問當a不再需要這塊記憶體,能否直接釋放它?答案是否定的,因為a並不知道b是否還在使用這塊記憶體,如果a釋放了,那麼b在使用這塊記憶體的時候會引起程式crash掉。
2.瞭解到1中assign的問題,那麼如何解決?最簡單的一個方法就是使用引用計數(reference counting),還是上面的那個例子,我們給那塊記憶體設一個引用計數,當記憶體被分配並且賦值給a時,引用計數是1。當把a賦值給b時引用計數增加到2。這時如果a不再使用這塊記憶體,它只需要把引用計數減1,表明自己不再擁有這塊記憶體。b不再使用這塊記憶體時也把引用計數減1。當引用計數變為0的時候,代表該記憶體不再被任何指針所引用,系統可以把它直接釋放掉。
總結:上面兩點其實就是assign和retain的區別,assign就是直接賦值,從而可能引起1中的問題,當數據為int, float等原生類型時,可以使用assign。retain就如2中所述,使用了引用計數,retain引起引用計數加1, release引起引用計數減1,當引用計數為0時,dealloc函數被調用,記憶體被回收。
__nullable和__nonnull
__nullable表示可以為nil
__nonnull表示不可以為nil