retain是指針拷貝,copy是內(nèi)容拷貝叫潦。在拷貝之前蝇完,都會釋放舊的對象。
?使用assign: 對基礎(chǔ)數(shù)據(jù)類型 (NSInteger)和C數(shù)據(jù)類型(int, float, double, char,等)
?使用copy: 對NSString
?使用retain: 對其他NSObject和其子類
assign: 簡單賦值矗蕊,不更改索引計數(shù)(Reference Counting)短蜕。
copy: 建立一個索引計數(shù)為1的對象,然后釋放舊對象
retain:釋放舊的對象傻咖,將舊對象的值賦予輸入對象朋魔,再提高輸入對象的索引計數(shù)為1
retain和copy還有assign的區(qū)別?
1.假設(shè)你用malloc分配了一塊內(nèi)存卿操,并且把它的地址賦值給了指針a警检,后來你希望指針b也共享這塊內(nèi)存,于是你又把a(bǔ)賦值給(assign)了b害淤。此時a和b指向同一塊內(nèi)存扇雕,請問當(dāng)a不再需要這塊內(nèi)存,能否直接釋放它窥摄?答案是否定的镶奉,因?yàn)閍并不知道b是否還在使用這塊內(nèi)存,如果a釋放了,那么b在使用這塊內(nèi)存的時候會引起程序crash掉哨苛。
2.了解到1中assign的問題鸽凶,那么如何解決?最簡單的一個方法就是使用引用計數(shù)(reference counting)建峭,還是上面的那個例子吱瘩,我們給那塊內(nèi)存設(shè)一個引用計數(shù),當(dāng)內(nèi)存被分配并且賦值給a時迹缀,引用計數(shù)是1使碾。當(dāng)把a(bǔ)賦值給b時引用計數(shù)增加到2。這時如果a不再使用這塊內(nèi)存祝懂,它只需要把引用計數(shù)減1票摇,表明自己不再擁有這塊內(nèi)存。b不再使用這塊內(nèi)存時也把引用計數(shù)減1砚蓬。當(dāng)引用計數(shù)變?yōu)?的時候矢门,代表該內(nèi)存不再被任何指針?biāo)茫到y(tǒng)可以把它直接釋放掉灰蛙。
3.上面兩點(diǎn)其實(shí)就是assign和retain的區(qū)別祟剔,assign就是直接賦值,從而可能引起1中的問題摩梧,當(dāng)數(shù)據(jù)為int, float等原生類型時物延,可以使用assign。retain就如2中所述仅父,使用了引用計數(shù)叛薯,retain引起引用計數(shù)加1, release引起引用計數(shù)減1,當(dāng)引用計數(shù)為0時笙纤,dealloc函數(shù)被調(diào)用耗溜,內(nèi)存被回收。
4.copy是在你不希望a和b共享一塊內(nèi)存時會使用到省容。a和b各自有自己的內(nèi)存抖拴。
5.atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作。
在多線程環(huán)境下腥椒,原子操作是必要的阿宅,否則有可能引起錯誤的結(jié)果。
atomic: 原子操作(原子性是指事務(wù)的一個完整操作寞酿,操作成功就提交家夺,反之就回滾. 原子操作就是指具有原子性的操作)在objective-c 屬性設(shè)置里面默認(rèn)的就是atomic,意思就是setter/getter函數(shù)是一個原子操作伐弹,如果多線程同時調(diào)用setter時拉馋,不會出現(xiàn)某一個線程執(zhí)行完setter所有語句之前榨为,另一個線程就開始執(zhí)行setter,相當(dāng)于函數(shù)頭尾加了鎖. 這樣的話并發(fā)訪問性能會比較低.
nonatomic: 非原子操作 一般不需要多線程支持的時候就用它煌茴,這樣在并發(fā)訪問的時候效率會比較高. 在objective-c里面通常對象類型都應(yīng)該聲明為非原子性的. iOS中程序啟動的時候系統(tǒng)只會自動生成一個單一的主線程.程序在執(zhí)行的時候一般情況下是在同一個線程里面對一個屬性進(jìn)行操作. 如果在程序中我們確定某一個屬性會在多線程中被使用随闺,并且需要做數(shù)據(jù)同步,就必須設(shè)置成原子性的蔓腐,但也可以設(shè)置成非原子性的矩乐,然后自己在程序中用加鎖之類的來做數(shù)據(jù)同步.通常說nonatomic 是提高在非多線程應(yīng)用中的讀寫效率.
注意,如果不加此屬性回论,則默認(rèn)是兩個訪問方法都為原子型事務(wù)訪問散罕。鎖被加到所屬對象實(shí)例級。
加了atomic傀蓉,setter函數(shù)會變成下面這樣:
if (property != newValue)
{
[property release];
property = [newValue retain];
}