OC中的屬性Property和點語法
屬性是什么
我們都知道,屬性是變量和它對應的setter和getter方法的集合,是一種語法糖,是一種簡化的寫法。也就是說,當你聲明了一個屬性的時候,你同時聲明了一個變量,一個setter方法,一個getter方法。
@property NSObject *property;
等價于
NSObject *_property;
- (void)setProperty:(NSObject *)property {
_property = property;
}
- (NSObject *)property {
return _property;
}
這次我們就來了解一下OC中屬性的一些特性。
對比Swift中的屬性類型
在Swift中,屬性是有很多類型的,有存儲屬性、計算屬性、延遲屬性、可選屬性、類屬性等。
Swift是以OC為基礎而設計的全新語言,它雖然有著全新的更全面的語法特性,但是依然能看出OC的影子。相反的,我們可以從Swift的對比中分析OC的一些特性。
存儲屬性
現(xiàn)在,我們聲明一個字符串屬性:
@property NSString *str;
這其實就是一個存儲屬性,因為他生成了一個變量用來存放字符串數(shù)據(jù)。
計算屬性
那計算屬性又是什么呢?
計算屬性不直接存儲值,而是提供一個 getter 來獲取值,一個可選的 setter 來間接設置其他屬性或變量的值。
根據(jù)上面的描述得出:就是沒有生成變量,只有setter/getter方法的屬性就是計算屬性。其實在很早之前,定義屬性的時候是不會生成變量的,需要使用 @synthesize str = _str; 這樣的方式來生成變量,同時定義變量的名稱。但在后來,Apple默認會生成變量。
那么在OC中,如何創(chuàng)建一個計算屬性呢?
在OC中,有這樣一條規(guī)則,如果聲明的屬性同時重寫了setter方法和getter方法,需要使用 @synthesize 重新聲明變量。也就是說,如果不聲明變量,他就是一個有著setter/getter方法的計算屬性。
那么如果只需要實現(xiàn)setter/getter方法中的其中一個的計算屬性怎么辦呢?這里就到了@dynamic關鍵字登場了。
被@dynamic`修飾的屬性在OC中被稱為動態(tài)屬性。顧名思義,就是用于動態(tài)計算的屬性。
@synthesize和@dynamic都是定義在@implementation下面的。
延遲屬性
Swift中的延遲屬性,在OC中的表現(xiàn)形式就是懶加載。
- (NSMutableArray *)dataSource {
if (!_dataSource) {
_dataSource = [[NSMutableArray alloc] init];
}
return _dataSource;
}
這是一個典型的懶加載模式,是通過重寫getter方法來動態(tài)的初始化變量,但是這樣的寫法并不完全滿足延遲屬性,因為該方法已經(jīng)無法獲取到nil這個值了。
可選屬性
在Swift中,每個對象初始化的時候,所有的存儲屬性必須得到初始化,為了簡化類的初始化,所以增添了可選型Optional。可選屬性默認值為nil。在OC中,所有定義的屬性并沒有強制初始化,所以都為可選屬性。
類屬性
類屬性,顧名思義就是類自身的屬性,他不屬于對象,而是屬于類本身。通過class修飾符實現(xiàn)。
@property (class, readonly, strong) NSUserDefaults *standardUserDefaults;
@property (class, readonly, strong) NSFileManager *defaultManager;
@property (class, readonly, strong) NSNotificationCenter *defaultCenter;
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) UIPasteboard *generalPasteboard;
#else
+ (UIPasteboard *)generalPasteboard;
#endif
如今iOS框架中的單例方法都從一個單例方法逐步變成了現(xiàn)在的類屬性的方式。
定義的類屬性需要使用
@dynamic修飾
點語法
點語法是跟隨屬性的應用而生的,是為了更加簡單方便的訪問屬性而出的語法特性。而他本質(zhì)上其實是一個動態(tài)方法,它無關乎是否是屬性,它只是轉換成對應setter/getter方法格式的參數(shù)來調(diào)用方法而已。
如下兩個方法也可以使用點語法來調(diào)用,就是這個道理。
- (id)copy;
- (id)mutableCopy;