assign:簡單賦值,不更改引用計(jì)數(shù)---基礎(chǔ)數(shù)據(jù)類型(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ù)類型的時(shí)候就使用copy,copy此特質(zhì)所表達(dá)的所屬關(guān)系與strong類似。然而設(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ì)象沒有變化。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)行訪問。
B,當(dāng)一個(gè)變量聲明為atomic時(shí),該變量為線程安全型,但是會(huì)影響訪問速度,
C,當(dāng)一個(gè)變量聲明為atomic時(shí),在非ARC編譯環(huán)境下,需要設(shè)置訪問鎖來保證對(duì)該變量進(jìn)行正確的get/set
nonatomic:表示非原子的,不會(huì)生成線程安全的代碼,速度比較快。iOS中的屬性一般都是使用它
A,? ? 當(dāng)一個(gè)變量聲明為nonatomic時(shí),意味著多個(gè)線程可以同時(shí)對(duì)其進(jìn)行訪問
B,? ? 當(dāng)一個(gè)變量聲明為nonatomic時(shí),它是非線程安全型,訪問速度快;
C,? ? 當(dāng)一個(gè)變量聲明為nonatomic時(shí),當(dāng)兩個(gè)不同的線程對(duì)其訪問時(shí),容易失控。
總結(jié):atomic和nonatomic用來決定編譯器生成的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,可以說保證了某種程度上的線程安全。nonatomic是不能保證線程安全的。但是nonatomic比atomic速度要快。這也是為什么property基本上都用nonatomic了。僅僅靠atomic來保證線程安全是不可能的,要寫出線程安全的代碼,還是需要有同步和互斥機(jī)制。
strong:ARC中默認(rèn)屬性,等于非ARC中的retain相對(duì)應(yīng)“擁有關(guān)系”為這種屬性設(shè)置新值時(shí),設(shè)置方法先保留新值,并釋放舊值,然后再將新值設(shè)置上去
應(yīng)用場景:strong屬性用于ARC中
@property (strong,nonatomic) ViewController *viewController;
weak:“非擁有關(guān)系”為這種屬性設(shè)置新值時(shí),設(shè)置方法既不保留新值,也不釋放舊值。此特質(zhì)同assign類似,然而屬性所指的對(duì)象遭到摧毀時(shí),屬性也會(huì)被清空(nil out)
應(yīng)用場景:用于IBOutlets,如,UIViewController的子類,即一般的控件。
@property (weak, nonatomic) IBOutlet UIButton *myButton;
strong與weak的區(qū)別:
前提:我們把要用strong或者weak的對(duì)象比作一只風(fēng)箏。風(fēng)箏想掙脫線的束縛,自由飛翔去,如果此時(shí)有一根線,那么這只風(fēng)箏就掙脫不了。
過程分析:
strong屬性的變量:當(dāng)我們把指向一只風(fēng)箏的變量聲明為strong時(shí),此時(shí),你就擁有控制這只風(fēng)箏的線,假如此時(shí)有五個(gè)人同時(shí)控制這只風(fēng)箏(即這只風(fēng)箏對(duì)象有三個(gè)strong類型的變量指向它),那么只有一種情況,這只風(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)箏飛走了,看不見了,不管有再多的觀眾,他們再也看不到風(fēng)箏了。
這個(gè)故事告訴我們一個(gè)道理:當(dāng)strong類型的指針被釋放掉之后,所有的指向同一個(gè)對(duì)象的weak指針都會(huì)被清零。從OC 2.0開始,我們能讓系統(tǒng)自動(dòng)生成設(shè)置變量值的方法或獲取變量值的方法,即系統(tǒng)會(huì)自動(dòng)為我們生成setter/getter方法。
控制權(quán)限的關(guān)鍵字:
readonly表示可以讀,只能生成getter方法。
readwrite表示可以讀可以寫,生成getter和setter方法的聲明與實(shí)現(xiàn)。
修改方法名稱的關(guān)鍵字:
getter表示修改生成的getter方法的名稱。一般情況下,BOOL類型的屬性的getter方法都是以is開頭的。
setter表示修改生成的setter方法的名稱,不過一般不修改。
注意: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類型,并且是NSArray類型,根據(jù)前面的分析,最好采用retain。所以默認(rèn)的assign會(huì)帶來警告提示。
unsafe_unretauined:用在ARC編譯環(huán)境下,在此環(huán)境下,與assign相似。它只是告訴ARC如何正確地調(diào)用聲明為unsafe_unretauined變量的retain和release,但是它適用于“對(duì)象類型”(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ù)類型
weak 對(duì)于循環(huán)應(yīng)用的時(shí)候,必須保證一段使用的是weak。如果不這樣你懂的。
總結(jié):
@property聲明的是屬性,而類后面加{}聲明的是成員變量,屬性跟成員變量是一回事,只是@property將我們的成員變量公開出去讓外部類可以調(diào)用,不允許外部訪問的統(tǒng)統(tǒng)寫在{}內(nèi)作為成員變量供自己內(nèi)部使用。
循環(huán)引用:指針的是兩個(gè)對(duì)象中,你中有我,我中有你。跟java中的一對(duì)一很相似。至于產(chǎn)生內(nèi)存泄露的原因主要是相互之前強(qiáng)指針指著對(duì)方,感覺跟java里面誰來hibernate設(shè)置誰來管理對(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:延長對(duì)象的釋放生命周期。
作用:把對(duì)象放進(jìn)離自己最近的那個(gè)自動(dòng)釋放池中。(它與對(duì)象在何地創(chuàng)建沒有關(guān)系,只要標(biāo)記上就放進(jìn)離自己最近的那個(gè)自動(dòng)釋放池中。)當(dāng)自動(dòng)釋放池銷毀的時(shí)候,它會(huì)把放在池中的所有對(duì)象進(jìn)行一次release操作。調(diào)用幾次autorelease,在自動(dòng)釋放池銷毀的時(shí)候就調(diào)用幾次release操作。在自動(dòng)釋放池中,只要是使用getter方法|構(gòu)造方法返回來的對(duì)象都是放在池中。
注意:在IOS 5(Xcode 4.2)以后加入了ARC機(jī)制,不需要再調(diào)用retain/release方法管理內(nèi)存了,但這并不是說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ì)被釋放。只要沒有強(qiáng)指針指向的對(duì)象,那么這個(gè)對(duì)象將會(huì)被立即被釋放。
(_weak弱指針標(biāo)識(shí)符)弱指針:不參與內(nèi)存管理,對(duì)內(nèi)存管理沒有影響。不會(huì)影響對(duì)象的回收。
注意:不要使用一個(gè)弱指針指向一個(gè)剛剛創(chuàng)建出來的對(duì)象,一旦這樣做,剛創(chuàng)建出來的對(duì)象馬上銷毀,在OC中也是自動(dòng)銷毀機(jī)制。當(dāng)出現(xiàn)循環(huán)引用的時(shí)候就必須要讓一端使用弱指針。