淺談Object-C的內存管理

? ? ? 在運行程序的過程中,需要創建大量的對象。對象從創建出來、使用之后,就需要對內存中的對象進行釋放,不然內存中的垃圾對象會越來越多,造成內存泄漏,從而嚴重影響程序的運行效率,甚至會引起系統的crash。而C#、JAVA等高級語言都有較為完善的回收機制(GC)來解決無效對象的問題。但是在Ojbc中卻缺少相應的較為完善的內存管理機制。在早先的Xcode版本中,對象的釋放需要開發者純手動進行釋放。目前Apple已經在近些年開始引入的自動回收的機制。但是并不是全自動的,所以主要講解一下Objc的內存管理問題。

首先,需要說明的是,Xcode4.2之后引入了ARC機制,是Xcode項目在啟動時默認的選項。需要自己手動關閉ARC功能。在Xcode中關閉ARC:項目屬性—Build Settings--搜索“garbage”找到Objective-C Automatic Reference Counting設置為No即可。


引用計數器

首先,在JAVA等高級語言中,GC會自動管理內存。當實例化一個對象之后會有一個變量來引用該對象(引用的實質是變量會存儲對象的物理地址),當該變量不再引用的時候,GC就會自動回收之前的對象。也就是說,創建的對象一旦沒有任何變量引用他,那么就將被回收。

但是,Ojbc中沒有類似的垃圾回收機制。而OC引入了對象引用計數器來管理內存。在OC中,每一個對象在生成之時都會有一個與他對應的整數(retainCount),叫做“引用計數器”,用來實時記錄改對象被引用與釋放的次數,當對象創建之初,就會被默認為reainCount為1。內存在判斷一個對象何時釋放的唯一依據就是判斷該對象的引用計數是否為0。在OC中,調用對象的alloc、retain、new、copy時,計數器都會自動的在原基礎上+1,當調用release時計數器-1。當release到對象的retainCount為0時,系統對調用該對象的dealloc方法將其銷毀。

舉例:

我創建一個ARCObject類,并且復寫它的dealloc對象方法

//? ARCObject.m

//? ARCTest

//

//? Created by workMAC on 16/8/12.

//? Copyright ? 2016年 yichen Wang. All rights reserved.

//

#import "ARCObject.h"

@implementation ARCObject

@synthesize number;

-(void)dealloc

{

NSLog(@"銷毀對象");

[super dealloc];

}

@end

在主函數做如下代碼調用:

ARCObject * ARCStr = [[ARCObject alloc] init];

[ARCStr retain];

NSLog(@"retainCount=%lu",[ARCStr retainCount]);

[ARCStr release];

NSLog(@"retainCount=%lu",[ARCStr retainCount]);

此時打印的retainCount為

2016-08-15 16:15:37.092 ARCTest[3717:184315] retainCount=2

2016-08-15 16:15:37.092 ARCTest[3717:184315] retainCount=1

可以看到在retain方法被調用后的retainCount加1,release減1。而此時再次release,則引用計數將變為0,代碼將執行ARCObject的dealloc方法。這時可以看到控制臺打?。?/p>

2016-08-15 16:22:10.215 ARCTest[3773:188463] 銷毀對象

注意:

在最終release銷毀對象成功以后,需要我們手動為ARCStr設置其變量為nil。否則會出現野指針的情況(即該對象已經不屬于本程序,在對他進行調用等操作是很危險的)還有一點就是,Objc中給空對象發送消息是不會引起什么錯誤的,所以應該注意釋放的嚴謹性和完整性。完整的釋放一個對象應該如此:

ARCObject * ARCStr = [[ARCObject alloc] init];

[ARCStr retain];

NSLog(@"retainCount=%lu",[ARCStr retainCount]);

[ARCStr release];

NSLog(@"retainCount=%lu",[ARCStr retainCount]);

[ARCStr release];

ARCStr = nil;

[ARCStr release];

內存釋放的原則

在項目中,手動管理面臨許多問題,尤其在對象之間來回引用的時候會造成很多不準確,即retain和release的計數最終并不能對應上。因此就需要遵循一個原則:誰創建,誰釋放。誰引用,誰釋放。


屬性參數

這里要講到的是我們在定義類所使用的對像時,@property括號中的內容問題。

在進行計數的時候,都是我們在方法里對對象進行retain、release的操作來控制它的引用計數器。那么通過@property其實是可以實現不調用對象的setter、getter方法來自動實現的。自動處理而不會造成內存泄漏。括號內的參數的意義如下:

從上邊也可以看到,@property的參數分為三類,也就是說它可以被三個不同種類的詞修飾。三個詞如果不設置,或者只設置一個,那么程序會默認三個的默認參數:(atomic,readwrite,assign),一個最安全,最基本的參數類型。

首先原子性來說,一般除非開啟線程使用atomic,否則請考慮使用nonatomic來修飾,它的性能更好,速度更快。

讀寫屬性,通俗講:readwrite可以對改對象之行讀寫操作,而readonly只能讀取不可寫入更改。

set的方法處理里,assign是直接賦值的。一般來說,在int等類型修飾較多。retain多用于非字符串的對象。copy多用來修飾字符串對象、block、NSArray、NSDictionary。

自動釋放池

Xcode4.2以后引入的ARC機制叫做“自動引用計數”(或“自動釋放池”),它相比前邊提到的JAVA等語言的內存管理差很多,其實也可以說是半自動的一種內存管理。它通過對@autoreleasepool聲明一個函數塊。

//? main.m

//? guigutang

//

//? Created by 王一臣 on 16/6/16.

//? Copyright ? 2016年 tuzhi Information Technology. All rights reserved.//#import#import "AppDelegate.h"

int main(int argc, char * argv[])

{

@autoreleasepool {

return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

}

}

那么生成一個對象,在初試進入這個方法時調用了autorelease,那么代碼執行完畢之后,在@autoreleasepool塊中,調用過autorelease的對象都將自動調用一次release。看到這里應該能明白了,OC中的自動管理,指的就是提對象自動釋放一次。所以它并不能保證對象一定會被回收,因為它只是調用一個release,并不是保證reatinCount為0。

注意:

1.自動緩存機制中,對象調用autorelease并不會引起retainCount的改變,只是把改對象放在了自動釋放池中。在@autoreleasepool塊執行完畢,最后對釋放池的對象統一release一次。

2.自動釋放池的ARC機制,實質是在程序最后統一調用對象的release方法一次,并不表示一定會銷毀對象(前頭有說過,銷毀對象的唯一依據是retainCount為0)

3.Objc中的類庫的靜態方法一般自帶autorelease方法,不需要手動釋放。

4.由于自動釋放池都是在程序最后統一銷毀對象,所以如果一個操作很占內存,,或者其對象在過程中非常占用內存,那么請考慮把對象不要放自動釋放池,或者說放在多個。最好是不好以來Xcode的ARC機制。比如SDWebImage在UITableview的框架下加載大量的高質量gif時,其實會有很大的內存漏洞,會直接導致APP內存爆炸,程序會出現crash。所以,內存管理還是需要非常重視的!

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

推薦閱讀更多精彩內容

  • 內存管理 簡述OC中內存管理機制。與retain配對使用的方法是dealloc還是release,為什么?需要與a...
    丶逐漸閱讀 1,978評論 1 16
  • 29.理解引用計數 Objective-C語言使用引用計數來管理內存,也就是說,每個對象都有個可以遞增或遞減的計數...
    Code_Ninja閱讀 1,512評論 1 3
  • 內存管理是程序在運行時分配內存、使用內存,并在程序完成時釋放內存的過程。在Objective-C中,也被看作是在眾...
    蹲瓜閱讀 3,132評論 1 8
  • iOS內存管理 概述 什么是內存管理 應用程序內存管理是在程序運行時分配內存(比如創建一個對象,會增加內存占用)與...
    蚊香醬閱讀 5,740評論 8 119
  • 內存管理 ARC處理原理 ARC是Objective-C編譯器的特性,而不是運行時特性或者垃圾回收機制,ARC所做...
    b485c88ab697閱讀 11,227評論 3 47