3. 屬性和關(guān)鍵字

==@property==
屬性 = 成員變量 + set方法 + get方法。

我們聲明一個(gè)屬性str的時(shí)候(@property),在編譯階段,編譯器會(huì)自動(dòng)給對(duì)象添加一個(gè)實(shí)例變量_str和它的存取方法- (void)setStr:(NSString *)str和- (NSString *)str。

==@synthesize==
@property (strong,nonatomic, readwrite) NSString *str;
@synthesize str = mystr;
@dynamic str;

@synthesize關(guān)鍵字主要有兩個(gè)作用,在ARC下已經(jīng)很少用了。

  • 在MRC下,@synthesize str這樣,編譯器才會(huì)自動(dòng)合成str的存取方法。不過(guò)在ARC下就不必了,無(wú)論你是否@synthesize str,編譯器都會(huì)自動(dòng)合成str的存取方法。
  • 如果你聲明的屬性是str,系統(tǒng)自動(dòng)給你添加的成員變量是_str,如果你對(duì)這個(gè)變量名字不滿,可以這樣@synthesize str = mystr;,自己給個(gè)名字。
==@dynamic==
  • 告訴編譯器不用為我們自動(dòng)合成變量的存起方法, 我們會(huì)自己實(shí)現(xiàn)。即使我們沒(méi)有實(shí)現(xiàn),編譯器也不會(huì)警告,因?yàn)樗嘈旁谶\(yùn)行階段會(huì)實(shí)現(xiàn)。
  • 如果我們?cè)谧宇?lèi)中重寫(xiě)父類(lèi)的屬性,就會(huì)報(bào)下面的警告
Auto property synthesis will not synthesize property 'str'; it will be implemented by its superclass, use @dynamic to acknowledge intention

因?yàn)槲覀兺瑫r(shí)在父類(lèi)和子類(lèi)中同時(shí)聲明了str的屬性,系統(tǒng)就不知道該在哪里(父類(lèi)Father還是子類(lèi)Son?)自動(dòng)合成str的存取方法,系統(tǒng)默認(rèn)是在父類(lèi)中聲明,因?yàn)樽宇?lèi)可以調(diào)用。不過(guò),系統(tǒng)希望我們顯式的聲明這一點(diǎn),這樣有利于提高代碼的可讀性。

#import "Son.h"
@implementation Son
@dynamic str;
@end
==讀寫(xiě)權(quán)限:readonly,readwrite==

屬性默認(rèn)都是readwrite的,表示可讀可寫(xiě),set/get方法編譯器都會(huì)自動(dòng)合成。如果用readonly修成屬性,表示該屬性是只讀的,編譯器只會(huì)自動(dòng)合成get方法, 不會(huì)合成set方法。另外,我們可以在.h文件中用readonly中修飾屬性,在.m文件類(lèi)擴(kuò)展中用readwrite修飾同一個(gè)屬性,這樣來(lái)防止外界篡改該屬性。

==原子性:nonatomic,atomic==

原子性(默認(rèn)):系統(tǒng)其它部分無(wú)法觀察到其中間步驟生成的臨時(shí)結(jié)果,而只能看到操作前與操作后的結(jié)果。

非原子性:nonatomic修飾的屬性不具有原子性,不使用同步鎖

屬性沒(méi)有atomic關(guān)鍵字,不過(guò)你用atomic修飾屬性,編譯器也不會(huì)報(bào)錯(cuò)。

  • atomic修飾的屬性的==存取(get,set)==方法是==線程安全==的。
  • 原子性==不能保證線程安全==,因?yàn)槿绻@過(guò)set方法給屬性賦值,就是線程不安全的了。
// atomic原子性的實(shí)現(xiàn)
- (void)setStr:(NSString *)str{
     @synchronized(self) {
         _str = str;
     }
}
==strong==
擁有關(guān)系

為屬性設(shè)置新值的時(shí)候,設(shè)置方法會(huì)先保留新值(新值的引用計(jì)數(shù)加一),并釋放舊值(舊值的引用計(jì)數(shù)減一),然后將新值賦值上去。

==weak==
非擁有關(guān)系

設(shè)置方法既不會(huì)保留新值(新值的引用計(jì)數(shù)加一),也不會(huì)釋放舊值(舊值的引用計(jì)數(shù)減一)。當(dāng)屬性所指的對(duì)象釋放的時(shí)候,屬性也會(huì)被置為nil。==為什么?==

==assign==
修飾基本數(shù)據(jù)(NSInteger,CGFloat等)類(lèi)型和對(duì)象。

當(dāng)assign用來(lái)修飾對(duì)象的時(shí)候,和weak類(lèi)似。唯一的區(qū)別就是當(dāng)屬性所指的對(duì)象釋放的時(shí)候,屬性不會(huì)被置為nil,這就會(huì)產(chǎn)生野指針。

==copy==
  • 設(shè)置新值的時(shí)候,當(dāng)新值是不可變的,和strong是一模一樣的。
  • 當(dāng)新值是可變的(開(kāi)頭是NSMutable),設(shè)置方法不會(huì)保留新值(新值的引用計(jì)數(shù)加一),而是對(duì)新值copy一份,不會(huì)影響新值的引用計(jì)數(shù)。
  • copy常用來(lái)修飾NSString,因?yàn)楫?dāng)新值是可變的,防止屬性在不知不覺(jué)中被修改
==__unsafe_unretained==
  • 用來(lái)修飾屬性的時(shí)候,和assing修飾對(duì)象的時(shí)候是一模一樣的。
  • __unsafe_unretained和__weak一樣,表示的是對(duì)象的一種弱引用關(guān)系
  • 為屬性設(shè)置新值的時(shí)候,設(shè)置方法既不會(huì)保留新值(新值的引用計(jì)數(shù)加一),也不會(huì)釋放舊值(舊值的引用計(jì)數(shù)減一)
  • __unsafe_unretained修飾的對(duì)象被釋放后,指針不會(huì)置空,而是變成一個(gè)野指針
==為什么有__weak還要用__unsafe_unretained呢?==

__weak對(duì)性能會(huì)有一定的消耗,使用__weak,需要檢查對(duì)象是否被釋放,在追蹤是否被釋放的時(shí)候當(dāng)然需要追蹤一些信息,那么此時(shí)__unsafe_unretained比__weak快,而且一個(gè)對(duì)象有大量的__weak引用對(duì)象的時(shí)候,當(dāng)對(duì)象被廢棄,那么此時(shí)就要遍歷weak表,把表里所有的指針置空,消耗cpu資源。

當(dāng)你明確對(duì)象的生命周期的時(shí)候,可以使用__unsafe_unretained替代__weak,可以稍微提高一些性能

==__block 和 __weak==
  • __block==會(huì)持有該對(duì)象==(需要掌握原理),即使超出了該對(duì)象的作用域,該對(duì)象還是會(huì)存在的,直到block對(duì)象從堆上銷(xiāo)毀;而__weak僅僅是將該對(duì)象賦值給weak對(duì)象,當(dāng)該對(duì)象銷(xiāo)毀時(shí),weak對(duì)象將指向nil;
  • __block可以讓block修改局部變量(賦值而不是使用,比如給數(shù)組添加元素不需要__block),而__weak不能。
  • MRC中__block是不會(huì)引起retain;但在ARC中__block則會(huì)引起retain。所以ARC中應(yīng)該使用__weak。
  • __block 在編譯后使局部基本數(shù)據(jù)類(lèi)型變?yōu)開(kāi)Block前綴命名的結(jié)構(gòu)體對(duì)象,包含isa指針,所以修改的是其地址,而不是值。
==__bridge和__bridge_transfer==
  • __bridge:CF和OC對(duì)象轉(zhuǎn)化時(shí)只涉及對(duì)象類(lèi)型不涉及對(duì)象所有權(quán)的轉(zhuǎn)化;
  • __bridge_transfer:常用在講CF對(duì)象轉(zhuǎn)換成OC對(duì)象時(shí),將CF對(duì)象的所有權(quán)交給OC對(duì)象,此時(shí)ARC就能自動(dòng)管理該內(nèi)存
  • __bridge_retained:(與__bridge_transfer相反)常用在將OC對(duì)象轉(zhuǎn)換成CF對(duì)象時(shí),將OC對(duì)象的所有權(quán)交給CF對(duì)象來(lái)管理
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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