細(xì)讀屬性特質(zhì)

“屬性”(property)是Objective-C的一項特性,用于封裝對象中的數(shù)據(jù)。使用屬性之后,編譯器會自動寫出一套存取方法,用以訪問給定類型中具有給定名稱的變量。該過程由編譯器在編譯期執(zhí)行,編輯器看不到這些合成方法的源代碼,編譯器還要自動向類中添加適當(dāng)?shù)膶嵗兞浚⑶以趯傩悦疤砑酉聞澗€,作為實例變量的名字。

1.常用關(guān)鍵字

  1. @synthesize : 用屬性property之后,會生成實例變量,默認(rèn)情況下是:_firstName,我們可以通過synthesize對實例變量名通過如下方式進(jìn)行修改:
    @ synthesize firstName = _myfirstName;

  2. @dynamic : 它可以用于阻止編譯器自動合成存取方法和實例變量。

2.屬性特質(zhì)

  1. 原子性(atomic,nonatomic)
    atomic:具備atomic特質(zhì)的獲取方法會通過鎖定機(jī)制來確保其操作的原子性。如果兩個線程讀寫同一屬性,無論何時總能看到有效的屬性值。
    nonatomic:不加鎖,當(dāng)一個線程在改寫屬性值時另外一個線程闖入,可能會把尚未修改好的的屬性值讀取出來,讀取到錯誤的屬性值。
    一般情況下我們都只是用nonatomic,原因如下:
    (1). 在iOS中使用同步鎖開銷較大,會帶來性能問題。
    (2). 即使屬性設(shè)置成原子性的也不能保證“線程安全”,要實現(xiàn)線程安全還需要更深層次的鎖定機(jī)制才行。
  2. 讀寫權(quán)限 (readwrite, readonly)
    readwrite: 擁有g(shù)etter/setter方法,若由synthesize實現(xiàn),編譯器會自動生成這兩個方法。
    readonly:僅擁有g(shù)etter方法,若由synthesize實現(xiàn),編譯器會自動生獲取方法。

3.內(nèi)存管理語義

  1. assign: "設(shè)置方法"之后執(zhí)行針對“純量類型”的簡單的賦值操作,如:NSIntager,CGFloat.
  2. strong:表明該屬性定義一種“擁有關(guān)系”,為這種屬性設(shè)置新值時,設(shè)置方法會先保留新值,并釋放舊值,再把新值設(shè)置上去。
  3. weak :該特質(zhì)表明屬性定義一種“非擁有關(guān)系”,為這種屬性設(shè)置新值時,設(shè)置方法既不保留新值,也不釋放舊值。
  4. copy:該設(shè)置方法并不保留新值,而是將其“拷貝”(copy),常用于NSString, NSDictionary, NSArray等數(shù)據(jù)類型來保護(hù)其封裝性。

原因:當(dāng)屬性類型為NSString* 時,傳遞給設(shè)置方法的新值有可能指向了個NSMutableString類的實例,這個類是NSString的子類,表示一種可以修改其值的字符串,若此時不拷貝字符串,那么設(shè)置完屬性之后,字符串的值就可能再對象不知情的情況下遭人更改。所以,這時就要拷貝一份“不可變”的字符串,以確保對象中的字符串值不會無疑將變動。只要實現(xiàn)屬性所用的對象是“可變的”,就應(yīng)該在設(shè)置屬性值時拷貝一份。

4.方法名

getter=<name> :指定“獲取方法”的方法名,如果某屬性是Boolean型時,想在獲取方法前加一個“is”前綴,就可以通過該方法來指定。如:

@property (nonatomic, getter = isOn) Bool on;

案例說明

  1. weak與strong的區(qū)別

     //copy,復(fù)制一份,相當(dāng)于retain,retainCount加1
     @property (nonatomic, copy) NSString *string1;
     //weak,與assign類似,retainCount不加1
     //指針指向的地址被釋放時,指針將被賦值為nil,有效的防止野指針。
     @property (nonatomic, weak) NSString *string2;
     //string1指向值為“string 1”的對象,retainCount=1
     self.string1 = [[NSString alloc] initWithUTF8String:"string 1"];
     //string2也指向值為“string 1”的對象,但是是若引用,retainCount不變
     self.string2 = self.string1;
     //將string1 指向nil, string1指向的地址被銷毀,值為“string 1”的對象的 retainCount=0,
     self.string1 = nil;
     //weak型的string2的指針也將被賦值為nil
     NSLog(@"String 2 = %@---%p", self.string2,self.string2);
    
     //打印結(jié)果:2016-07-05 13:55:27.400 Test[1328:34343] String 2 = (null)---0x0
    

如果將上面string2的特性weak更改成strong或者copy,string2將不會指向nil,打印的結(jié)果如下:
2016-07-05 14:13:57.352 Test[1391:43333] String 2 = string 1---0x79ff0d30

  1. copy與strong的區(qū)別

從上面看出copy和strong都能實現(xiàn)一種“擁有關(guān)系”,也就是使retainCount 加1,為什么一般情況下我們都是將NSString,NSArray,NSDictionary等屬性設(shè)置為copy,而不是strong呢?

那是因為,NSString,NSArray,NSDictionary等類,都有對應(yīng)的可變類型,如NSMutableString,NSMutableArray,NSMutableDictionary。NSMutableString這個類是NSString類的子類,表示一種可以修改其值的字符串,若此時不拷貝字符串,那么設(shè)置完屬性之后,字符串的值就可能再對象不知情的情況下遭人更改。

案例如下:

@property (nonatomic, copy) NSString *string1;
@property (nonatomic, strong) NSString *string3;
@property (nonatomic, weak) NSString *string2;

NSMutableString *mStr = [NSMutableString stringWithFormat:@"abc"];
self.string1 = mStr;
self.string2 = mStr;
self.string3 = mStr;

[mStr appendString:@"de"];
NSLog(@"mStr:%@---%p---%p",  mStr,mStr,&mStr);
NSLog(@"copyStr:%@---%p---%p", self.string1,self.string1, &_string1);
NSLog(@"strongStr:%@---%p---%p",   self.string3,self.string3, &_string3);
NSLog(@"weakStr:%@---%p---%p",   self.string2,self.string2, &_string2);

打印的結(jié)果如下:

2016-07-05 14:23:32.886 Test[1458:51397] mStr:abcde---0x7a67eaf0---0xbff2201c
2016-07-05 14:23:32.886 Test[1458:51397] copyStr:abc---0x7a67e410---0x7b06587c
2016-07-05 14:23:32.886 Test[1458:51397] weakStr:abcde---0x7a67eaf0---0x7b065880
2016-07-05 14:23:32.886 Test[1458:51397] strongStr:abcde---0x7a67eaf0---0x7b065884

由上面的打印結(jié)果可以看出:
1、設(shè)置特性為copy的string1,在執(zhí)行[mStr appendString:@"de"];后沒有被修改,而設(shè)置為strong,weak的屬性都遭到修改。
2、strong對應(yīng)的*string3、weak對應(yīng)的*string2指向的指針和*mStr指向的地址相同,說明他們指向的是*mStr相同的地址,他們的區(qū)別只存在于計數(shù)器是否加1。而copy對應(yīng)的*string2卻是指向不同于*mStr指向的地址,說明它是復(fù)制了一份重新開辟的內(nèi)存,并且retainCount加1。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容