assign:簡(jiǎn)單賦值韵丑,不更改引用計(jì)數(shù)---基礎(chǔ)數(shù)據(jù)類(lèi)型(NSInteger蜈项,CGFloat怒详,int, float, double, char, 等)
retain:與strong相對(duì)應(yīng)措伐,使用了引用計(jì)數(shù)鳖谈,retain+1,release -1;當(dāng)引用 計(jì)數(shù)為0時(shí),dealloc會(huì)被調(diào)用波俄,內(nèi)存被釋放晨逝。
copy:當(dāng)屬性是NSString數(shù)據(jù)類(lèi)型的時(shí)候就使用copy,copy此特質(zhì)所表達(dá)的所屬關(guān)系與strong類(lèi)似弟断。然而設(shè)置方法并不保留新值咏花,而是將其“拷貝”
copy與retain的具體區(qū)別為:copy其實(shí)是建立了一個(gè)相同的對(duì)象趴生,而retain只是保存其對(duì)象阀趴,并且其計(jì)數(shù)值+1昏翰。
例如:一個(gè)NSString對(duì)象,地址為0×1000刘急,內(nèi)容為@”string”棚菊,copy到另外一個(gè)NSString之后,地址為0×2000叔汁,內(nèi)容相同统求,新的對(duì)象retain為1,舊有對(duì)象沒(méi)有變化据块。retain到另外一個(gè)NSString之后码邻,地址相同(建立一個(gè)指針,指針拷貝)另假,內(nèi)容當(dāng)然相同像屋,但是這個(gè)新對(duì)象的retain值+1,并釋放舊的對(duì)象边篮。
so己莺。。戈轿。retain是指針拷貝凌受,copy是內(nèi)容拷貝。
atomic:A思杯,當(dāng)一個(gè)變量聲明為atomic時(shí)胜蛉,意味著在多線程中只能有一個(gè)線程能對(duì)它進(jìn)行訪問(wèn)。
B智蝠,當(dāng)一個(gè)變量聲明為atomic時(shí)腾么,該變量為線程安全型,但是會(huì)影響訪問(wèn)速度杈湾,
C解虱,當(dāng)一個(gè)變量聲明為atomic時(shí),在非ARC編譯環(huán)境下漆撞,需要設(shè)置訪問(wèn)鎖來(lái)保證對(duì)該變量進(jìn)行正確的get/set
nonatomic:表示非原子的殴泰,不會(huì)生成線程安全的代碼,速度比較快浮驳。iOS中的屬性一般都是使用它
A悍汛,? ? 當(dāng)一個(gè)變量聲明為nonatomic時(shí),意味著多個(gè)線程可以同時(shí)對(duì)其進(jìn)行訪問(wèn)
B至会,? ? 當(dāng)一個(gè)變量聲明為nonatomic時(shí)离咐,它是非線程安全型,訪問(wèn)速度快;
C宵蛀,? ? 當(dāng)一個(gè)變量聲明為nonatomic時(shí)昆著,當(dāng)兩個(gè)不同的線程對(duì)其訪問(wèn)時(shí),容易失控术陶。
總結(jié):atomic和nonatomic用來(lái)決定編譯器生成的getter和setter是否為原子操作凑懂。
在多線程環(huán)境下,原子操作是必要的梧宫,否則有可能引起錯(cuò)誤的結(jié)果接谨。加了atomic,setter函數(shù)會(huì)變成下面這樣:
if (property != newValue) {
[property release];
property = [newValue retain];
}
atomicity的默認(rèn)值是atomic塘匣,讀取函數(shù)為原子操作脓豪。atomic是保證讀取變量是線程安全的,即它會(huì)保證每次getter和setter的操作都會(huì)正確的執(zhí)行完畢忌卤,而不用擔(dān)心其它線程在你get的時(shí)候set跑揉,可以說(shuō)保證了某種程度上的線程安全。nonatomic是不能保證線程安全的埠巨。但是nonatomic比atomic速度要快历谍。這也是為什么property基本上都用nonatomic了。僅僅靠atomic來(lái)保證線程安全是不可能的辣垒,要寫(xiě)出線程安全的代碼望侈,還是需要有同步和互斥機(jī)制。
strong:ARC中默認(rèn)屬性勋桶,等于非ARC中的retain相對(duì)應(yīng)“擁有關(guān)系”為這種屬性設(shè)置新值時(shí)脱衙,設(shè)置方法先保留新值,并釋放舊值例驹,然后再將新值設(shè)置上去
應(yīng)用場(chǎng)景:strong屬性用于ARC中
@property (strong,nonatomic) ViewController *viewController;
weak:“非擁有關(guān)系”為這種屬性設(shè)置新值時(shí)捐韩,設(shè)置方法既不保留新值,也不釋放舊值鹃锈。此特質(zhì)同assign類(lèi)似荤胁,然而屬性所指的對(duì)象遭到摧毀時(shí),屬性也會(huì)被清空(nil out)
應(yīng)用場(chǎng)景:用于IBOutlets,如屎债,UIViewController的子類(lèi)仅政,即一般的控件。
@property (weak, nonatomic) IBOutlet UIButton *myButton;
strong與weak的區(qū)別:
前提:我們把要用strong或者weak的對(duì)象比作一只風(fēng)箏盆驹。風(fēng)箏想掙脫線的束縛圆丹,自由飛翔去,如果此時(shí)有一根線躯喇,那么這只風(fēng)箏就掙脫不了辫封。
過(guò)程分析:
strong屬性的變量:當(dāng)我們把指向一只風(fēng)箏的變量聲明為strong時(shí),此時(shí),你就擁有控制這只風(fēng)箏的線倦微,假如此時(shí)有五個(gè)人同時(shí)控制這只風(fēng)箏(即這只風(fēng)箏對(duì)象有三個(gè)strong類(lèi)型的變量指向它)檀咙,那么只有一種情況,這只風(fēng)箏才會(huì)掙脫掉線的束縛:這三個(gè)人都放掉手中的線璃诀,(release)
weak屬性的變量:當(dāng)我們把指向一只風(fēng)箏的變量聲明為weak時(shí),此時(shí)蔑匣,就像站在旁邊看風(fēng)箏的觀眾們一樣劣欢,當(dāng)上面的三個(gè)人還握著手中的線時(shí),他們只能看到風(fēng)箏裁良,并不能控制它凿将,他們能做的只能是用手指指向風(fēng)箏,并大喊价脾,“看牧抵,那只風(fēng)箏飛得真高!”侨把,然而犀变,當(dāng)上面的三個(gè)人把手中的線都放掉時(shí),此時(shí)秋柄,風(fēng)箏飛走了获枝,看不見(jiàn)了,不管有再多的觀眾骇笔,他們?cè)僖部床坏斤L(fēng)箏了省店。
這個(gè)故事告訴我們一個(gè)道理:當(dāng)strong類(lèi)型的指針被釋放掉之后,所有的指向同一個(gè)對(duì)象的weak指針都會(huì)被清零笨触。從OC 2.0開(kāi)始懦傍,我們能讓系統(tǒng)自動(dòng)生成設(shè)置變量值的方法或獲取變量值的方法,即系統(tǒng)會(huì)自動(dòng)為我們生成setter/getter方法芦劣。
控制權(quán)限的關(guān)鍵字:
readonly表示可以讀粗俱,只能生成getter方法。
readwrite表示可以讀可以寫(xiě)虚吟,生成getter和setter方法的聲明與實(shí)現(xiàn)源梭。
修改方法名稱(chēng)的關(guān)鍵字:
getter表示修改生成的getter方法的名稱(chēng)。一般情況下稍味,BOOL類(lèi)型的屬性的getter方法都是以is開(kāi)頭的废麻。
setter表示修改生成的setter方法的名稱(chēng),不過(guò)一般不修改模庐。
注意:readonly關(guān)鍵字代表setter不會(huì)被生成烛愧,所以它不可以和copy/retain/assign組合使用。默認(rèn)的property行為有:atomic,assign怜姿,readwrite慎冤。如果這樣使用:@property? BOOL _flag;//代表這_flag有著atomic,assign沧卢,readwrite三種行為蚁堤。所以我們一定要提防這種默認(rèn)行為潛在的危險(xiǎn)。
如:@property NSMutableArray *photoViews;//此時(shí)會(huì)有警告出現(xiàn)但狭,因?yàn)镹SMutableArray是一種obj類(lèi)型披诗,并且是NSArray類(lèi)型,根據(jù)前面的分析立磁,最好采用retain呈队。所以默認(rèn)的assign會(huì)帶來(lái)警告提示。
unsafe_unretauined:用在ARC編譯環(huán)境下唱歧,在此環(huán)境下宪摧,與assign相似。它只是告訴ARC如何正確地調(diào)用聲明為unsafe_unretauined變量的retain和release颅崩,但是它適用于“對(duì)象類(lèi)型”(object type)几于,該特質(zhì)表達(dá)一種“非擁有關(guān)系”(“不保留”,unretained)沿后,當(dāng)目標(biāo)對(duì)象遭到摧毀時(shí)孩革,屬性值不會(huì)自動(dòng)清空(“不安全”,unsafe)得运,這一點(diǎn)與weak有區(qū)別
在ARC中的@property:
strong ?對(duì)所有的普通OC對(duì)象
copy 對(duì)字符串
assign 基本數(shù)據(jù)類(lèi)型
weak 對(duì)于循環(huán)應(yīng)用的時(shí)候膝蜈,必須保證一段使用的是weak。如果不這樣你懂的熔掺。
總結(jié):
@property聲明的是屬性饱搏,而類(lèi)后面加{}聲明的是成員變量,屬性跟成員變量是一回事置逻,只是@property將我們的成員變量公開(kāi)出去讓外部類(lèi)可以調(diào)用推沸,不允許外部訪問(wèn)的統(tǒng)統(tǒng)寫(xiě)在{}內(nèi)作為成員變量供自己內(nèi)部使用。
循環(huán)引用:指針的是兩個(gè)對(duì)象中券坞,你中有我鬓催,我中有你。跟java中的一對(duì)一很相似恨锚。至于產(chǎn)生內(nèi)存泄露的原因主要是相互之前強(qiáng)指針指著對(duì)方宇驾,感覺(jué)跟java里面誰(shuí)來(lái)hibernate設(shè)置誰(shuí)來(lái)管理對(duì)方。(在這里我們引入了強(qiáng)指針與弱指針在ARC中會(huì)提到猴伶,這里不做解釋课舍。)解決循環(huán)引用的方式:讓其中一方設(shè)置為assign塌西。多個(gè)對(duì)象之間不要封閉環(huán),如果出現(xiàn)封閉的環(huán)筝尾,那么環(huán)中所有的對(duì)象將得不到釋放捡需。
解決的方法,讓其中一端為虛線筹淫。
自動(dòng)釋放池:(自動(dòng)釋放池是一個(gè)棧)
autorelease:延長(zhǎng)對(duì)象的釋放生命周期站辉。
作用:把對(duì)象放進(jìn)離自己最近的那個(gè)自動(dòng)釋放池中。(它與對(duì)象在何地創(chuàng)建沒(méi)有關(guān)系损姜,只要標(biāo)記上就放進(jìn)離自己最近的那個(gè)自動(dòng)釋放池中饰剥。)當(dāng)自動(dòng)釋放池銷(xiāo)毀的時(shí)候,它會(huì)把放在池中的所有對(duì)象進(jìn)行一次release操作薛匪。調(diào)用幾次autorelease,在自動(dòng)釋放池銷(xiāo)毀的時(shí)候就調(diào)用幾次release操作脓鹃。在自動(dòng)釋放池中逸尖,只要是使用getter方法|構(gòu)造方法返回來(lái)的對(duì)象都是放在池中。
注意:在IOS 5(Xcode 4.2)以后加入了ARC機(jī)制瘸右,不需要再調(diào)用retain/release方法管理內(nèi)存了娇跟,但這并不是說(shuō)ARC會(huì)自動(dòng)回收內(nèi)存,它只是自動(dòng)加入了retain/release的代碼太颤,OC的內(nèi)存管理機(jī)制依然是計(jì)數(shù)機(jī)制苞俘。assign生成的set方法中依然不會(huì)被自動(dòng)加入retain/release代碼。
ARC(automatic Reference Counting)自動(dòng)內(nèi)存管理
ARC中編譯器的特性:編譯器會(huì)在適當(dāng)?shù)臅r(shí)候龄章,加入內(nèi)存管理的代碼吃谣。(_strong強(qiáng)指針標(biāo)識(shí)符,默認(rèn)所有的指針都是強(qiáng)指針)
作用:只要強(qiáng)指針指向的對(duì)象做裙,那么這個(gè)對(duì)象就不會(huì)被釋放岗憋。只要沒(méi)有強(qiáng)指針指向的對(duì)象,那么這個(gè)對(duì)象將會(huì)被立即被釋放锚贱。
(_weak弱指針標(biāo)識(shí)符)弱指針:不參與內(nèi)存管理仔戈,對(duì)內(nèi)存管理沒(méi)有影響。不會(huì)影響對(duì)象的回收拧廊。
注意:不要使用一個(gè)弱指針指向一個(gè)剛剛創(chuàng)建出來(lái)的對(duì)象监徘,一旦這樣做,剛創(chuàng)建出來(lái)的對(duì)象馬上銷(xiāo)毀吧碾,在OC中也是自動(dòng)銷(xiāo)毀機(jī)制凰盔。當(dāng)出現(xiàn)循環(huán)引用的時(shí)候就必須要讓一端使用弱指針。