iOS--property屬性常用的關(guān)鍵字

在開發(fā)中,我們iOS在定義屬性的時候,需要在括號property()內(nèi)說明該屬性的特性,因為屬性的特性決定了屬性在原子性、存取方法、內(nèi)存管理三個方面的特性。首先屬性property有兩大概念:ivar(實例變量)、存取方法(access method=getter),即@property = ivar + getter + setter。如:

@property(nonatomic,copy)NSString *name;

類完成屬性的定以后,編譯器會自動編寫訪問這些屬性的方法(自動合成autosynthesis),上述代碼寫出來的類等效與下面的代碼:

- (NSString *)name;  
- (void)setName:(NSString *)name;

再看看常用的特性關(guān)鍵字,大概有9個,分為原子性、讀寫方法、內(nèi)存管理三組:

1、nonatomic / atomic
2、readonly / readwrite
3、retain / copy / strong /weak / assign

下面我們就分別看下這幾個關(guān)鍵字:

原子性:(nonatomic / atomic)

atomic(系統(tǒng)默認):atomic,提供多線程安全,在多線程環(huán)境下,原子操作是必要的,否則有可能引起錯誤的結(jié)果。加了atomic,setter函數(shù)會變成下面這樣:

@property(retain) UITextField *userName;

//系統(tǒng)生成的代碼如下:
- (UITextField *) userName {
    UITextField *retval = nil;
    @synchronized(self) {
        retval = [[userName retain] autorelease];
    }
    return retval;
}

- (void) setUserName:(UITextField *)userName_ {
    @synchronized(self) {
      [userName release];
      userName = [userName_ retain];
    }
}

多線程中只能有一個線程能對它進行訪問該變量為線程安全型,但是會影響訪問速度,在非ARC編譯環(huán)境下,需要設(shè)置訪問鎖來保證對該變量進行正確的getter/setter。

nonatomic(常用):nonatomic跟atomic剛好相反,表示非原子的,可以被多個線程訪問。它的效率比atomic快,但不能保證在多線程環(huán)境下的安全性,在單線程和明確只有一個線程訪問的情況下廣泛使用。多個線程可以同時對其進行訪問,訪問速度快;當一個變量聲明為nonatomic時,setter函數(shù)會變成下面這樣:

@property(nonatomic, retain) UITextField *userName;

//系統(tǒng)生成的代碼如下:
- (UITextField *) userName {
    return userName;
}

- (void) setUserName:(UITextField *)userName_ {
    [userName_ retain];
    [userName release];
    userName = userName_;
}

atomic是Objc使用的一種線程保護技術(shù),基本上來講,是防止在寫未完成的時候被另外一個線程讀取,造成數(shù)據(jù)錯誤。而這種機制是耗費系統(tǒng)資源的,所以在iPhone這種小型設(shè)備上,如果沒有使用多線程間的通訊編程,那么nonatomic是一個非常好的選擇;那居然我們一般都是用nonatomic ,那系統(tǒng)為什么還是默認用atomic 呢?這是因為iOS 用 nonatomic 比較好,而 OSX 用 atomic相對較好。如果不寫的話,系統(tǒng)按照相對比較安全的 atomic 處理。iOS 用nonatomic主要是出于性能考慮,OSX 上性能不是問題,所以使用了atomic。

注意:
??atomic的作用只是給getter和setter加了個鎖,atomic只能保證代碼進入getter或者setter函數(shù)內(nèi)部時是安全的,一旦出了getter和setter,多線程安全只能靠程序員自己保障了。所以atomic屬性和使用property的多線程安全并沒什么直接的聯(lián)系。另外,atomic由于加鎖也會帶來一些性能損耗,所以我們在編寫iOS代碼的時候,一般聲明property為nonatomic,在需要做多線程安全的場景,自己去額外加鎖做同步。

存取方法:(readonly / readwrite)

從字面上看的出來,意思很簡單:

readwrite(系統(tǒng)默認):可讀可寫,表示該屬性同時擁有setter和getter。

設(shè)置器和讀取器都需要在@implementation中實現(xiàn)。如果使用@synthesize關(guān)鍵字,讀取器和設(shè)置器都會被解析。

readonly:只讀屬性,表示只有g(shù)etter沒有setter,不希望屬性在類外改變;

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

內(nèi)存管理(retain 、copy 、strong、weak、assign)

retain:釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數(shù)為1,對其他NSObject和其子類,對參數(shù)進行release舊值,再retain新值,指定retain會在賦值時喚醒傳入值的retain消息。此屬性只能用于Objective-C對象類型,而不能用于Core Foundation對象。使用:對其他NSObject和其子類;

copy: setter方法進行copy操作,與retain處理流程一樣,先舊值release,再copy出新的對象,retainCount為1。這是為了減少對上下文的依賴而引入的機制。 copy是在你不希望a和b共享一塊內(nèi)存時會使用到。a和b各自有自己的內(nèi)存。retain是指針拷貝,copy是內(nèi)容拷貝;使用:NSString,NSArray,NSDictionary及其可變子類;

注意:當類擁有mutable子類時,你應該使用copy,而不是retain。
例如:NSAArray,NSSet,NSDictionary,NSData的,NSCharacterSet,NSIndexSet,NSString;

strong(ARC中默認):強引用,表示實例變量對傳入的對象要有所有權(quán)關(guān)系;在ARC環(huán)境下等同于retain;使用:自定義對象,控制器對象;比如我們傳Model的時候必須用strong,否則會崩潰!

weak:弱引用,在setter方法中,需要對傳入的對象不進行引用計數(shù)加1的操作。簡單來說,就是對傳入的對象沒有所有權(quán),當該對象引用計數(shù)為0時,即該對象被釋放后,用weak聲明的實例變量指向nil,即實例變量的值為0。使用:代理對象,IBOutlet;

assign: 簡單賦值,不更改索引計數(shù),適用簡單數(shù)據(jù)類型。使用:int、float、double和NSInteger,CGFloat等;

聲明: 轉(zhuǎn)載請注明出處http://www.itdecent.cn/p/c2d51763d164

最后編輯于
?著作權(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)容