iOS聲明屬性常用關(guān)鍵字解析


聲明屬性時,在ARC環(huán)境下會經(jīng)常用到幾個關(guān)鍵字nonatomicatomic、readonly、readwritestrong、copy、assign 、weak等,使用過程中并不是很得心應(yīng)手,因此做個總結(jié)。

非ARC環(huán)境下的retain、 release就不在這里贅述了。

屬性的參數(shù)應(yīng)該按照下面的順序排列: 原子性,讀寫 和 內(nèi)存管理。 這樣做你的屬性更容易修改正確,并且更好閱讀。(譯者注:習(xí)慣上修改某個屬性的修飾符時,一般從屬性名從右向左搜索需要修動的修飾符。最可能從最右邊開始修改這些屬性的修飾符,根據(jù)經(jīng)驗這些修飾符被修改的可能性從高到低應(yīng)為:內(nèi)存管理 > 讀寫權(quán)限 >原子操作)
引用自《禪與 Objective-C 編程藝術(shù)》

原子操作

  • nonatomic :非原子性訪問,對屬性賦值的時候不加鎖,多線程并發(fā)訪問會提高性能。如果不加此屬性,則默認是兩個訪問方法都為原子性訪問;

  • atomic:置成員變量的@property屬性時,默認為atomic,提供多線程安全,在多線程環(huán)境下,原子操作是必要的,否則有可能引起錯誤的結(jié)果。

atomic的意思就是setter/getter這個函數(shù),是一個原語操作。如果有多個線程同時調(diào)用setter的話,不會出現(xiàn)某一個線程執(zhí)行完setter全部語句之前,另一個線程開始執(zhí)行setter情況,相當(dāng)于函數(shù)頭尾加了鎖一樣,可以保證數(shù)據(jù)的完整性。nonatomic不保證setter/getter的原語性,所以你可能會取到不完整的東西。因此,在多線程的環(huán)境下原子操作是非常必要的,否則有可能會引起錯誤的結(jié)果。

比如setter函數(shù)里面改變兩個成員變量,如果你用nonatomic的話,getter可能會取到只更改了其中一個變量時候的狀態(tài),這樣取到的東西會有問題,就是不完整的。當(dāng)然如果不需要多線程支持的話,用nonatomic就夠了,因為不涉及到線程鎖的操作,所以它執(zhí)行率相對快些。

在默認情況下,由編譯器所合成的方法會通過鎖定機制確保其原子性(atomicity)。如果屬性具備 nonatomic特質(zhì),則不使用同步鎖。請注意,盡管沒有名為“atomic”的特質(zhì)(如果某屬性不具備nonatomic特質(zhì),那它就是“原子的”(atomic)。

在iOS開發(fā)中,幾乎所有屬性都聲明為 nonatomic。
一般情況下并不要求屬性必須是“原子的”,因為這并不能保證“線程安全” ( thread safety),若要實現(xiàn)“線程安全”的操作,還需采用更為深層的鎖定機制才行。例如,一個線程在連續(xù)多次讀取某屬性值的過程中有別的線程在同時改寫該值,那么即便將屬性聲明為 atomic,也還是會讀到不同的屬性值。

因此,開發(fā)iOS程序時一般都會使用 nonatomic 屬性。但是在開發(fā) Mac OS X 程序時,使用 atomic 屬性通常都不會有性能瓶頸。

讀寫

  • readwrite:同時產(chǎn)生setter\getter方法

此標(biāo)記說明屬性會被當(dāng)成讀寫的,這也是默認屬性。設(shè)置器和讀取器都需要在@implementation中實現(xiàn)。如果使用@synthesize關(guān)鍵字,讀取器和設(shè)置器都會被解析。

  • readonly:只產(chǎn)生簡單的getter,沒有setter。

此標(biāo)記說明屬性是只讀的,默認的標(biāo)記是讀寫,如果你指定了只讀,在@implementation中只需要一個讀取器?;蛘呷绻闶褂聾synthesize關(guān)鍵字,也是有讀取器方法被解析。而且如果你試圖使用點操作符為屬性賦值,你將得到一個編譯錯誤。

內(nèi)存管理

  • strong:在ARC環(huán)境下等同于retain,聲明屬性的默認關(guān)鍵字。(淺拷貝,拷貝指針)

  • copy:深拷貝,拷貝內(nèi)容,copy 就是復(fù)制一個不可變 Object 的對象

Example:

//.h文件
@property (nonatomic, copy) NSMutableArray mutableArray;

//.m文件
NSMutableArray *array = [NSMutableArray arrayWithObjects:@1,@2,nil];
self.mutableArray = array;
[self.mutableArray removeObjectAtIndex:0];

上述代碼,如果成員變量 mutableArray 使用 copy,在 self.mutableArray = array;執(zhí)行后,self.mutableArray只是拷貝了array的內(nèi)容,并沒有拷貝array的指針,所有self.mutableArray實際不可變,所以無法執(zhí)行removeObjectAtIndex:操作;

補充說明self.mutableArray拷貝了array的內(nèi)容,在拷貝過程中其實只是拿到了array的所有object的指針,也就是淺拷貝了array的所有object。

Example:

//.h文件
@property (nonatomic, copy) NSMutableArray mutableArray;

//.m文件

NSMutableString *string = [[NSMutableString alloc]initWithString:@"123456"];
NSMutableArray *array = [[NSMutableArray alloc]initWithObjects:string, nil];
self.mutableArray = array;
[string deleteCharactersInRange:NSMakeRange(1, 1)];
 NSLog(@"%@",self.mutableArray);

上述代碼,最后打印結(jié)果為:

2017-06-05 00:08:39.190 YYProject[88423:1877006] (
    13456
)
  • assign:基礎(chǔ)數(shù)據(jù)類型(NSInteger,CGFloat)和C數(shù)據(jù)類型(int, float, double, char等)使用

  • weak:對象銷毀之后會自動置為nil,防止野指針。

Delegate基本總是使用weak,以防止循環(huán)引用。特殊情況是,希望在dealloc中調(diào)用delegate的某些方法進行釋放,此時如果使用weak將引起異常,因為此時已經(jīng)是nil了,那么采用assign更為合適,這時需要自己手動在dealloc中給Delegate置為nil。


iOS開發(fā)——OC篇&常用關(guān)鍵字的使用與區(qū)別 - iCocos - 博客園

《招聘一個靠譜的iOS》面試題參考答案(上)

iOS#

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容