assign: 簡單賦值,不更改索引計數
copy: 創建一個索引計數爲1的對象,而後釋放舊對象
retain:釋放舊的對象,將舊對象的值賦予輸入對象,再提升輸入對象的索引計數爲1多線程
Copy實際上是創建了一個相同的對象,而retain不是:
好比一個NSString對象,地址爲0×1111,內容爲@」STR」
Copy到另一個NSString之 後,地址爲0×2222,內容相同,新的對象retain爲1, 舊有對象沒有變化併發
retain到另一個NSString之 後,地址相同(創建一個指針,指針拷貝),內容固然相同,這個對象的retain值+1函數
也就是說,retain是指針拷貝,copy是內容拷貝。在拷貝以前,都會釋放舊的對象。性能
* 使用assign: 對基礎數據類型 (NSInteger)和C數據類型(int, float, double, char,等)
* 使用copy: 對NSString
* 使用retain: 對其餘NSObject和其子類atom
1.readonly表示這個屬性是隻讀的,就是隻生成getter方法,不會生成setter方法.
2.readwrite,設置可供訪問級別
3.retain,是說明該屬性在賦值的時候,先release以前的值,而後再賦新值給屬性,引用再加1。
4.nonatomic,非原子性訪問,不加同步,多線程併發訪問會提升性能。注意,若是不加此屬性,則默認是兩個訪問方法都爲原子型事務訪問。.net
retain和copy還有assign的區別線程
1. 假設你用malloc分配了一塊內存,而且把它的地址賦值給了指針a,後來你但願指針b也共享這塊內存,因而你又把a賦值給(assign)了b。此時a和b指向同一塊內存,請問當a再也不須要這塊內存,可否直接釋放它?答案是否認的,由於a並不知道b是否還在使用這塊內存,若是a釋放了,那麼b在使用這塊內存的時候會引發程序crash掉。指針
2. 瞭解到1中assign的問題,那麼如何解決?最簡單的一個方法就是使用引用計數(reference counting),仍是上面的那個例子,咱們給那塊內存設一個引用計數,當內存被分配而且賦值給a時,引用計數是1。當把a賦值給b時引用計數增長到2。這時若是a再也不使用這塊內存,它只須要把引用計數減1,代表本身再也不擁有這塊內存。b再也不使用這塊內存時也把引用計數減1。當引用計數變爲0的時候,表明該內存再也不被任何指針所引用,系統能夠把它直接釋放掉。對象
3. 上面兩點其實就是assign和retain的區別,assign就是直接賦值,從而可能引發1中的問題,當數據爲int, float等原生類型時,可使用assign。retain就如2中所述,使用了引用計數,retain引發引用計數加1, release引發引用計數減1,當引用計數爲0時,dealloc函數被調用,內存被回收。
4. copy是在你不但願a和b共享一塊內存時會使用到。a和b各自有本身的內存。
5. atomic和nonatomic用來決定編譯器生成的getter和setter是否爲原子操做。在多線程環境下,原子操做是必要的,不然有可能引發錯誤的結果。加了atomic,setter函數會變成下面這樣:
if (property != newValue) {
[property release];
property = [newValue retain];
}blog
關於retain,copy,assign的區別問題其實困擾我好久了,由於在程序中不太經常使用到copy,assign,因此三者的具體差異一直不太明白。
按照個人理解,assign和retain的區別,就是引入了一個計數器retaincount,就能夠對一個內存的釋放方便不少。copy,就是把原來的內存複製一遍,使各自都擁有一個內存,這樣釋放的時候也不會出錯。
assign: 簡單賦值,不更改索引計數(Reference Counting)。
copy: 創建一個索引計數爲1的對象,而後釋放舊對象
retain:釋放舊的對象,將舊對象的值賦予輸入對象,再提升輸入對象的索引計數爲1
使用assign: 對基礎數據類型 (NSInteger,CGFloat)和C數據類型(int, float, double, char, 等等)
使用copy: 對NSString
使用retain: 對其餘NSObject和其子類
nonatomic,非原子性訪問,不加同步,多線程併發訪問會提升性能。注意,若是不加此屬性,則默認是兩個訪問方法都爲原子型事務訪問
@property(nonatomic, retain) UITextField *userName編譯時自動生成的代碼
- (UITextField *) userName {
return userName;
}
- (void) setUserName:(UITextField *)userName_ {
[userName release];
userName = [userName_ retain];
}
@property(retain) UITextField *userName自動生成的代碼
- (UITextField *) userName {
UITextField *retval = nil;
@synchronized(self) {
retval = [[userName retain] autorelease];
}
return retval;
}
- (void) setUserName:(UITextField *)userName_ {
@synchronized(self) {
[userName release];
userName = [userName_ retain];
}
}
摘自 青峯專欄