iOS中assign、copy、retain關(guān)鍵字的含義
現(xiàn)在開始為讀者朋友們?cè)敿?xì)介紹了assign、copy、retain關(guān)鍵字的含義,區(qū)別等。
assign: 簡(jiǎn)單賦值,不更改索引計(jì)數(shù)
copy: 建立一個(gè)索引計(jì)數(shù)為1的對(duì)象,然后釋放舊對(duì)象
retain:釋放舊的對(duì)象,將舊對(duì)象的值賦予輸入對(duì)象,再提高輸入對(duì)象的索引計(jì)數(shù)為1
Copy其實(shí)是建立了一個(gè)相同的對(duì)象,而retain不是:
比如一個(gè)NSString對(duì)象,地址為0×1111,內(nèi)容為@”STR”
Copy到另外一個(gè)NSString之 后,地址為0×2222,內(nèi)容相同,新的對(duì)象retain為1, 舊有對(duì)象沒有變化
retain到另外一個(gè)NSString之 后,地址相同(建立一個(gè)指針,指針拷貝),內(nèi)容當(dāng)然相同,這個(gè)對(duì)象的retain值+1
也就是說(shuō),retain是指針拷貝,copy是內(nèi)容拷貝。在拷貝之前,都會(huì)釋放舊的對(duì)象。
* 使用assign:對(duì)基礎(chǔ)數(shù)據(jù)類型 (NSInteger)和C數(shù)據(jù)類型(int, float, double, char,等)
* 使用copy: 對(duì)NSString
* 使用retain: 對(duì)其他NSObject和其子類
1.readonly表示這個(gè)屬性是只讀的,就是只生成getter方法,不會(huì)生成setter方法.
2.readwrite,設(shè)置可供訪問(wèn)級(jí)別
3.retain,是說(shuō)明該屬性在賦值的時(shí)候,先release之前的值,然后再賦新值給屬性,引用再加1。
4.nonatomic,非原子性訪問(wèn),不加同步,多線程并發(fā)訪問(wèn)會(huì)提高性能。注意,如果不加此屬性,則默認(rèn)是兩個(gè)訪問(wèn)方法都為原子型事務(wù)訪問(wèn)。
retain和copy還有assign的區(qū)別
1. 假設(shè)你用malloc分配了一塊內(nèi)存,并且把它的地址賦值給了指針a,后來(lái)你希望指針b也共享這塊內(nèi)存,于是你又把a(bǔ)賦值給(assign)了b。此時(shí)a 和b指向同一塊內(nèi)存,請(qǐng)問(wèn)當(dāng)a不再需要這塊內(nèi)存,能否直接釋放它?答案是否定的,因?yàn)閍并不知道b是否還在使用這塊內(nèi)存,如果a釋放了,那么b在使用這塊 內(nèi)存的時(shí)候會(huì)引起程序crash掉。
2. 了解到1中assign的問(wèn)題,那么如何解決?最簡(jiǎn)單的一個(gè)方法就是使用引用計(jì)數(shù)(reference counting),還是上面的那個(gè)例子,我們給那塊內(nèi)存設(shè)一個(gè)引用計(jì)數(shù),當(dāng)內(nèi)存被分配并且賦值給a時(shí),引用計(jì)數(shù)是1。當(dāng)把a(bǔ)賦值給b時(shí)引用計(jì)數(shù)增加到 2。這時(shí)如果a不再使用這塊內(nèi)存,它只需要把引用計(jì)數(shù)減1,表明自己不再擁有這塊內(nèi)存。b不再使用這塊內(nèi)存時(shí)也把引用計(jì)數(shù)減1。當(dāng)引用計(jì)數(shù)變?yōu)?的時(shí)候, 代表該內(nèi)存不再被任何指針?biāo)?,系統(tǒng)可以把它直接釋放掉。
3. 上面兩點(diǎn)其實(shí)就是assign和retain的區(qū)別,assign就是直接賦值,從而可能引起1中的問(wèn)題,當(dāng)數(shù)據(jù)為int, float等原生類型時(shí),可以使用assign。retain就如2中所述,使用了引用計(jì)數(shù),retain引起引用計(jì)數(shù)加1, release引起引用計(jì)數(shù)減1,當(dāng)引用計(jì)數(shù)為0時(shí),dealloc函數(shù)被調(diào)用,內(nèi)存被回收。
4. copy是在你不希望a和b共享一塊內(nèi)存時(shí)會(huì)使用到。a和b各自有自己的內(nèi)存。
5. atomic和nonatomic用來(lái)決定編譯器生成的getter和setter是否為原子操作。在多線程環(huán)境下,原子操作是必要的,否則有可能引起錯(cuò)誤的結(jié)果。加了atomic,setter函數(shù)會(huì)變成下面這樣:
- if (property != newValue) {
- [property release];
- property = [newValue retain];
- }
關(guān)于retain,copy,assign的區(qū)別問(wèn)題其實(shí)困擾我很久了,因?yàn)樵诔绦蛑胁惶S玫絚opy,assign,所以三者的具體差別一直不太明白。
按照我的理解,assign和retain的區(qū)別,就是引入了一個(gè)計(jì)數(shù)器retaincount,就可以對(duì)一個(gè)內(nèi)存的釋放方便很多。copy,就是把原來(lái)的內(nèi)存復(fù)制一遍,使各自都擁有一個(gè)內(nèi)存,這樣釋放的時(shí)候也不會(huì)出錯(cuò)。
assign: 簡(jiǎn)單賦值,不更改索引計(jì)數(shù)(Reference Counting)。
copy: 建立一個(gè)索引計(jì)數(shù)為1的對(duì)象,然后釋放舊對(duì)象
retain:釋放舊的對(duì)象,將舊對(duì)象的值賦予輸入對(duì)象,再提高輸入對(duì)象的索引計(jì)數(shù)為1
使用assign: 對(duì)基礎(chǔ)數(shù)據(jù)類型 (NSInteger,CGFloat)和C數(shù)據(jù)類型(int, float, double, char, 等等)
使用copy: 對(duì)NSString
使用retain: 對(duì)其他NSObject和其子類
nonatomic,非原子性訪問(wèn),不加同步,多線程并發(fā)訪問(wèn)會(huì)提高性能。注意,如果不加此屬性,則默認(rèn)是兩個(gè)訪問(wèn)方法都為原子型事務(wù)訪問(wèn)
- @property(nonatomic, retain) UITextField *userName編譯時(shí)自動(dòng)生成的代碼
- - (UITextField *) userName {
- return userName;
- }
- - (void) setUserName:(UITextField *)userName_ {
- [userName release];
- userName = [userName_ retain];
- }
- @property(retain) UITextField *userName自動(dòng)生成的代碼
- - (UITextField *) userName {
- UITextField *retval = nil;
- @synchronized(self) {
- retval = [[userName retain] autorelease];
- }
- return retval;
- }
- - (void) setUserName:(UITextField *)userName_ {
- @synchronized(self) {
- [userName release];
- userName = [userName_ retain];
- }
- }
介紹完了assigne、copy、retain關(guān)鍵字含義之后,相信你一定自己有了初步的理解和自己的想法,歡迎交流探討。