淺談Object-C的內(nèi)存管理

? ? ? 在運(yùn)行程序的過程中,需要創(chuàng)建大量的對象磅轻。對象從創(chuàng)建出來马澈、使用之后痊班,就需要對內(nèi)存中的對象進(jìn)行釋放,不然內(nèi)存中的垃圾對象會越來越多馒胆,造成內(nèi)存泄漏,從而嚴(yán)重影響程序的運(yùn)行效率睦尽,甚至?xí)鹣到y(tǒng)的crash当凡。而C#纠俭、JAVA等高級語言都有較為完善的回收機(jī)制(GC)來解決無效對象的問題。但是在Ojbc中卻缺少相應(yīng)的較為完善的內(nèi)存管理機(jī)制朴则。在早先的Xcode版本中乌妒,對象的釋放需要開發(fā)者純手動進(jìn)行釋放外邓。目前Apple已經(jīng)在近些年開始引入的自動回收的機(jī)制坐榆。但是并不是全自動的,所以主要講解一下Objc的內(nèi)存管理問題匹中。

首先豪诲,需要說明的是屎篱,Xcode4.2之后引入了ARC機(jī)制,是Xcode項(xiàng)目在啟動時默認(rèn)的選項(xiàng)重虑。需要自己手動關(guān)閉ARC功能缺厉。在Xcode中關(guān)閉ARC:項(xiàng)目屬性—Build Settings--搜索“garbage”找到Objective-C Automatic Reference Counting設(shè)置為No即可。


引用計數(shù)器

首先命爬,在JAVA等高級語言中辐脖,GC會自動管理內(nèi)存嗜价。當(dāng)實(shí)例化一個對象之后會有一個變量來引用該對象(引用的實(shí)質(zhì)是變量會存儲對象的物理地址),當(dāng)該變量不再引用的時候练链,GC就會自動回收之前的對象奴拦。也就是說错妖,創(chuàng)建的對象一旦沒有任何變量引用他疚沐,那么就將被回收亮蛔。

但是,Ojbc中沒有類似的垃圾回收機(jī)制辣吃。而OC引入了對象引用計數(shù)器來管理內(nèi)存。在OC中芬探,每一個對象在生成之時都會有一個與他對應(yīng)的整數(shù)(retainCount)神得,叫做“引用計數(shù)器”,用來實(shí)時記錄改對象被引用與釋放的次數(shù)偷仿,當(dāng)對象創(chuàng)建之初哩簿,就會被默認(rèn)為reainCount為1。內(nèi)存在判斷一個對象何時釋放的唯一依據(jù)就是判斷該對象的引用計數(shù)是否為0酝静。在OC中节榜,調(diào)用對象的alloc、retain别智、new宗苍、copy時亿遂,計數(shù)器都會自動的在原基礎(chǔ)上+1浓若,當(dāng)調(diào)用release時計數(shù)器-1渺杉。當(dāng)release到對象的retainCount為0時,系統(tǒng)對調(diào)用該對象的dealloc方法將其銷毀挪钓。

舉例:

我創(chuàng)建一個ARCObject類是越,并且復(fù)寫它的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

在主函數(shù)做如下代碼調(diào)用:

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方法被調(diào)用后的retainCount加1,release減1碌上。而此時再次release倚评,則引用計數(shù)將變?yōu)?,代碼將執(zhí)行ARCObject的dealloc方法馏予。這時可以看到控制臺打犹煳唷:

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

注意:

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

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];

內(nèi)存釋放的原則

在項(xiàng)目中,手動管理面臨許多問題突那,尤其在對象之間來回引用的時候會造成很多不準(zhǔn)確挫酿,即retain和release的計數(shù)最終并不能對應(yīng)上。因此就需要遵循一個原則:誰創(chuàng)建愕难,誰釋放早龟。誰引用,誰釋放猫缭。


屬性參數(shù)

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

在進(jìn)行計數(shù)的時候饵骨,都是我們在方法里對對象進(jìn)行retain翘悉、release的操作來控制它的引用計數(shù)器。那么通過@property其實(shí)是可以實(shí)現(xiàn)不調(diào)用對象的setter居触、getter方法來自動實(shí)現(xiàn)的妖混。自動處理而不會造成內(nèi)存泄漏。括號內(nèi)的參數(shù)的意義如下:

從上邊也可以看到轮洋,@property的參數(shù)分為三類制市,也就是說它可以被三個不同種類的詞修飾。三個詞如果不設(shè)置弊予,或者只設(shè)置一個祥楣,那么程序會默認(rèn)三個的默認(rèn)參數(shù):(atomic,readwrite,assign),一個最安全,最基本的參數(shù)類型误褪。

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

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

set的方法處理里帜羊,assign是直接賦值的咒程。一般來說,在int等類型修飾較多讼育。retain多用于非字符串的對象帐姻。copy多用來修飾字符串對象、block窥淆、NSArray卖宠、NSDictionary。

自動釋放池

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

//? 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]));

}

}

那么生成一個對象,在初試進(jìn)入這個方法時調(diào)用了autorelease鳖宾,那么代碼執(zhí)行完畢之后吼砂,在@autoreleasepool塊中,調(diào)用過autorelease的對象都將自動調(diào)用一次release鼎文。看到這里應(yīng)該能明白了渔肩,OC中的自動管理,指的就是提對象自動釋放一次拇惋。所以它并不能保證對象一定會被回收周偎,因?yàn)樗皇钦{(diào)用一個release,并不是保證reatinCount為0撑帖。

注意:

1.自動緩存機(jī)制中蓉坎,對象調(diào)用autorelease并不會引起retainCount的改變,只是把改對象放在了自動釋放池中胡嘿。在@autoreleasepool塊執(zhí)行完畢蛉艾,最后對釋放池的對象統(tǒng)一release一次。

2.自動釋放池的ARC機(jī)制,實(shí)質(zhì)是在程序最后統(tǒng)一調(diào)用對象的release方法一次勿侯,并不表示一定會銷毀對象(前頭有說過拓瞪,銷毀對象的唯一依據(jù)是retainCount為0)

3.Objc中的類庫的靜態(tài)方法一般自帶autorelease方法,不需要手動釋放助琐。

4.由于自動釋放池都是在程序最后統(tǒng)一銷毀對象吴藻,所以如果一個操作很占內(nèi)存,弓柱,或者其對象在過程中非常占用內(nèi)存沟堡,那么請考慮把對象不要放自動釋放池,或者說放在多個矢空。最好是不好以來Xcode的ARC機(jī)制航罗。比如SDWebImage在UITableview的框架下加載大量的高質(zhì)量gif時,其實(shí)會有很大的內(nèi)存漏洞屁药,會直接導(dǎo)致APP內(nèi)存爆炸粥血,程序會出現(xiàn)crash。所以酿箭,內(nèi)存管理還是需要非常重視的复亏!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市缭嫡,隨后出現(xiàn)的幾起案子缔御,更是在濱河造成了極大的恐慌,老刑警劉巖妇蛀,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耕突,死亡現(xiàn)場離奇詭異,居然都是意外死亡评架,警方通過查閱死者的電腦和手機(jī)眷茁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纵诞,“玉大人上祈,你說我怎么就攤上這事≌丬剑” “怎么了登刺?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茁裙。 經(jīng)常有香客問我塘砸,道長,這世上最難降的妖魔是什么晤锥? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任掉蔬,我火速辦了婚禮廊宪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘女轿。我一直安慰自己箭启,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布蛉迹。 她就那樣靜靜地躺著傅寡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪北救。 梳的紋絲不亂的頭發(fā)上荐操,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音珍策,去河邊找鬼托启。 笑死,一個胖子當(dāng)著我的面吹牛攘宙,可吹牛的內(nèi)容都是我干的屯耸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蹭劈,長吁一口氣:“原來是場噩夢啊……” “哼疗绣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起铺韧,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤多矮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后祟蚀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體工窍,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年前酿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鹏溯。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡罢维,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出丙挽,到底是詐尸還是另有隱情肺孵,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布颜阐,位于F島的核電站平窘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏凳怨。R本人自食惡果不足惜瑰艘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一是鬼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧紫新,春花似錦均蜜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至偶芍,卻和暖如春充择,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背匪蟀。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工椎麦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人萄窜。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓铃剔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親查刻。 傳聞我的和親對象是個殘疾皇子键兜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 內(nèi)存管理 簡述OC中內(nèi)存管理機(jī)制。與retain配對使用的方法是dealloc還是release穗泵,為什么普气?需要與a...
    丶逐漸閱讀 1,964評論 1 16
  • 29.理解引用計數(shù) Objective-C語言使用引用計數(shù)來管理內(nèi)存,也就是說佃延,每個對象都有個可以遞增或遞減的計數(shù)...
    Code_Ninja閱讀 1,487評論 1 3
  • 內(nèi)存管理是程序在運(yùn)行時分配內(nèi)存现诀、使用內(nèi)存,并在程序完成時釋放內(nèi)存的過程履肃。在Objective-C中仔沿,也被看作是在眾...
    蹲瓜閱讀 3,072評論 1 8
  • iOS內(nèi)存管理 概述 什么是內(nèi)存管理 應(yīng)用程序內(nèi)存管理是在程序運(yùn)行時分配內(nèi)存(比如創(chuàng)建一個對象,會增加內(nèi)存占用)與...
    蚊香醬閱讀 5,723評論 8 119
  • 內(nèi)存管理 ARC處理原理 ARC是Objective-C編譯器的特性,而不是運(yùn)行時特性或者垃圾回收機(jī)制尺棋,ARC所做...
    b485c88ab697閱讀 11,204評論 3 47