IOS中(assign,retain,copy,weak,strong)的區別以及nonatomic的含義

我們在聲明@property 屬性時,總是要在括號中寫上assign、retain、copy、weak、strong中的一個,很多時候,我們僅僅只是按照習慣去寫經常寫的那一個,但有時候看代碼時又會發現別人用的不盡相同,那這些之間的區別是什么呢?
首先,上面五個并不是在一個層面上的,可以分為兩部分,第一部分是assign、retain、copy,第二部分是weak、strong。
我們先說第一部分的assign、retain、copy。
assign:
assign一般用來修飾基本的數據類型,包括基礎數據類型 (NSInteger,CGFloat)和C數據類型(int, float, double, char, 等等),為什么呢?assign聲明的屬性是不會增加引用計數的,也就是說聲明的屬性釋放后,就沒有了,即使其他對象用到了它,也無法留住它,只會crash。但是,即使被釋放,指針卻還在,成為了野指針,如果新的對象被分配到了這個內存地址上,又會crash,所以一般只用來聲明基本的數據類型,因為它們會被分配到棧上,而棧會由系統自動處理,不會造成野指針。
retain:
與assign相對,我們要解決對象被其他對象引用后釋放造成的問題,就要用retain來聲明。retain聲明后的對象會更改引用計數,那么每次被引用,引用計數都會+1,釋放后就會-1,即使這個對象本身釋放了,只要還有對象在引用它,就會持有,不會造成什么問題,只有當引用計數為0時,就被dealloc析構函數回收內存了。
copy:
最常見到copy聲明的應該是NSString。copy與retain的區別在于retain的引用是拷貝指針地址,而copy是拷貝對象本身,也就是說retain是淺復制,copy是深復制,如果是淺復制,當修改對象值時,都會被修改,而深復制不會。之所以在NSString這類有可變類型的對象上使用,是因為它們有可能和對應的可變類型如NSMutableString之間進行賦值操作,為了防止內容被改變,使用copy去深復制一份。copy工作由copy方法執行,此屬性只對那些實現了NSCopying協議的對象類型有效 。
以上三個可以在MRC中使用,但是weak和strong就只能在ARC中使用,也就是自動引用計數,這時就不能手動去進行retain、release等操作了,ARC會幫我們完成這些工作。
(在說明白retain和copy的區別,首先需要明白深復制和淺復制的概念。
1 深拷貝:深拷貝是指拷貝對象的具體內容,而內存地址是自主分配的,拷貝結束之后,兩個對象雖然存的值是相同的,但是內存地址不一樣,兩個對象也互不影響,互不干涉。
2 淺拷貝:淺拷貝就是對內存地址的復制,讓目標對象指針和源對象指向同一片內存空間。在 iOS 里面, 使用retain 關鍵字進行引用計數,就是一種更加保險的淺拷貝。他既讓幾個指針共用同一片內存空間,又可以在release 由于計數的存在,不會輕易的銷毀內存,達到更加簡單使用的目的。

只有不可變對象創建不可變副本(copy)才是淺復制,其它的都是深復制
下面通過實驗來說明copy和retain的區別。

@interface ViewController ()@property (nonatomic,copy) NSString *name;
@property (nonatomic,retain) NSString *name2;
@end
-(void)test{ 
    NSString *str = @"fffff"; 
    self.name = str; 
    self.name2 = str; NSLog(@" str: %p",str); 
    NSLog(@" copy:  %p",self.name); 
    NSLog(@"retain: %p",self.name2);
}

-(void)test2{
     NSMutableString *str = [NSMutableString stringWithString:@"ffffff"]; 
     self.name = str; self.name2 = str;
     NSLog(@" strM: %p",str); 
     NSLog(@" copy: %p",self.name); 
     NSLog(@"retaini: %p",self.name2);
}

先執行test,再執行test2,兩次執行的結果如下:

test執行結果截圖
test2執行結果截圖

下面來分析一下:
(1)在test中,str指向一個不可變的NSString對象,地址為0x9d040,然后str分別給name和name2賦值,由于name和name2都是NSString對象,所有都屬于淺復制,賦值后都是指向str對象地址0x9d040,所有打印結果三者指向同一個對象。
(2)在test2中,str指向一個可變的NSMutableString對象,地址為0x7c140e60,然后分別給name和name2賦值,此時copy對應的name是深復制,所以會復制出另一個對象,地址為0x7c148b80。而retain對應的name2依然指向str對象地址0x7c140e60,所以打印結果是str和name2對應同一地址,name對應另一個地址。
所以得出結論:
(1)copy是創建一個新對象,兩個對象內容相同,舊對象沒有變化。新的對象retain為1,與舊有對象的引用計數不變。舊對象發生改變不影響新對象,copy減少對象對上下文的依賴。
(2)retain屬性表示兩個對象地址相同(建立一個指針,指針拷貝),內容相同,這個對象的retain值+1。兩個對象要改變就一起改變。
(3)如果把一個對象賦值給另一個對象(如上面把str賦值給name或name2),如果該對象是不可變的,那么另一個對象是copy或者retain都可以,沒區別;把一個對象賦值給另一個對象,如果該對象是可變的,并且希望另一個對象隨著該對象變化而變化,則可以把另一個對象設置為retain(如上面把str賦值給name2);如果希望另一個對象不隨著該對象變化而變化,則可以把另一個對象設置為copy(如上面把str賦值給name)。
記住一點即可,如果復制的是不可變類型,那么copy并沒有開辟新的內存,而是進行了一次淺拷貝。當然了,在實際應用中,copy返回的是不可變對象,mutableCopy返回的是可變對象,除此之外,其他都不影響使用。)

weak:
weak其實類似于assign,叫弱引用,也是不增加引用計數。一般只有在防止循環引用時使用,比如父類引用了子類,子類又去引用父類。IBOutlet、Delegate一般用的就是weak,這是因為它們會在類外部被調用,防止循環引用。
strong:
相對的,strong就類似與retain了,叫強引用,會增加引用計數,類內部使用的屬性一般都是strong修飾的,現在ARC已經基本替代了MRC,所以我們最常見的就是strong了。

nonatomic:
在修飾屬性時,我們往往還會加一個nonatomic,這又是什么呢?它的名字叫非原子訪問。對應的有atomic,是原子性的訪問。我們知道,在使用多線程時為了避免在寫操作時同時進行寫導致問題,經常會對要寫的對象進行加鎖,也就是同一時刻只允許一個線程去操作它。如果一個屬性是由atomic修飾的,那么系統就會進行線程保護,防止多個寫操作同時進行。這有好處,但也有壞處,那就是消耗系統資源,所以對于iPhone這種小型設備,如果不是進行多線程的寫操作,就可以使用nonatomic,取消線程保護,提高性能。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379

推薦閱讀更多精彩內容