課程要點:ios
內存管理的必要性學習
OC是一門面向對象的語言,在軟件運行過程當中會創造大量的對象,每建立一個對象系統就會給其分配一塊內存,若是開發者不對建立的這些對象進行管理,當這個軟件佔用系統20兆內存時,iPhone開始發出內存警告,若是佔用30兆內存時,iPhone OS會關閉應用程序。爲了不這種狀況咱們須要對我們建立的對象進行管理。管理方式有MRC(手動管理)、ARC(自動管理)。spa
MRC在11年之後,漸漸的被開發者所拋棄,但爲何開發者還要學習這個東西呢。舉個例子,就比如小時候家裏的各類物品通常都是母親進行整理,咱們基本上不多管這些事,但咱們多多少少都知道母親整理物品的習慣,咱們須要找什麼東西時,只要按照母親的習慣去找就行。若是一點都不知道母親整理物品的習慣,這對咱們找東西將會很麻煩。指針
在比較正規的公司,他們對項目的要求是很嚴格的。項目作完他們會對你作的項目進行一個內存檢測,若是太高,他們會讓你進行重構,此時若是你不知道你的項目是怎麼管理內存的,那不是就是抓瞎麼。code
MRC對象
在WWDC2011和iOS5以前,蘋果開發者一直都在使用MRC進行內存管理。blog
由於如今Xcode建立的工程默認都是由ARC管理的。因此在使用MRC以前要關閉ARC,如圖所示繼承
轉過MRC後看代碼:內存
PS:我以前已經建立過Person類,因此採用下面代碼以前先在你項目裏新建一個Person類開發
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { @autoreleasepool { /* object-c 使用引用計數的方式管理內存。當咱們使用一個指針指向一塊內存的時候,應該對這塊內存作retain操做,那麼引用計數加一。當咱們再也不使用這個指針指向這塊內存,應該對這塊內存作release操做,那麼引用計數減一。這樣可使引用計數值一直保持等於指向這塊內存的指針數量。retainCount返回當前內存的引用計數值。當內存被開闢後,默認的引用計數爲1 。 */ //產生一個新的對象,此時不用release,由於新建的對象引用爲1,不須要爲第一個指向這個對象的指針額外加一計數。 Person *person1 = [[Person alloc]init]; NSInteger count = [person1 retainCount]; //賦值後count等於1 NSLog(@"%ld",count); NSObject *person2 = person1; [person2 retain]; count = [person2 retainCount]; //賦值後count等於2 NSLog(@"%ld",count); //須要認識的是,不論使用object1仍是object2調用retain方法都是同樣的,由於二者指向同一塊內存,計數增長減小都是之內存爲對象的 [person1 release],person1 = NULL; //當object2 release以後,這個對象的引用計數爲0,內存被釋放,同時會調用這個對象的delloc方法。delloc方法是每個類都有的隱式方法。當用這個類建立的對象的retainCount爲0的時候纔會調用,本身能夠在.m文件中將他重寫.若是此時你打印retainCount你會發現他的值依然是1,這裏你們只須要記住系統內部會對咱建立的對象進行操做,纔會形成這種現象。沒必要深究。 [person2 release],person2 = NULL;
/* * object release 以後爲何還要把對象給置空 由於對象其實就是一個指針,指針指向的是一塊內存,release僅僅是把這個內存釋放了,也就是說release之後系統把這塊內存給回收了。但此時指針指向得仍是這塊內存。這是不符合邏輯的,全部我要把指針給置空,至此才切斷了這個指針與對象的全部關係。 */ } return 0; }
輸出結果:
2015-11-27 17:47:32.162 Test[2333:228117] 1 2015-11-27 17:47:32.163 Test[2333:228117] 2 Program ended with exit code: 0
重寫Person.m裏的delloc方法
#import "Person.h" @implementation Person //這是一個隱式方法,也就是蘋果在內部已經聲明和實現好了,若是我想要使用直接調用即可,若是想改變裏面的內容,只需在.m裏面把他重寫就行。 - (void)dealloc{ NSLog(@"person對象被釋放"); [super dealloc]; /* * 爲何須要調用父類的dealloc方法 子類的某些實例是繼承自父類的。所以,咱們須要調用父類的dealloc方法,來釋放父類擁有的這些對象。 PS:每個類都有一個父類,用到這個類時不可避免的會用到父類裏面的東西,因此我們在子類裏釋放內存的時候,要記得經過[super dealloc]來釋放掉我們用到的父類裏面的對象。 調用的順序通常來講調用的順序是,當子類的對象釋放完時,而後再釋放父類的所擁有的實例。 */ } @end
輸出結果:
2015-11-27 18:13:32.355 Test[2403:238207] 1 2015-11-27 18:13:32.356 Test[2403:238207] 2 2015-11-27 18:13:32.356 Test[2403:238207] person對象被釋放 Program ended with exit code: 0
自動釋放池:
一、Autorelease pool
自動釋放池(Autorelease pool)是OC的一種內存自動回收機制,能夠將一些臨時變量經過自動釋放池來回收統一釋放
自動釋放池本事銷燬的時候,池子裏面全部的對象都會作一次release操做
二、autorelease
任何OC對象只要調用autorelease方法,就會把該對象放到離本身最近的自動釋放池中(棧頂的釋放池)。
自動釋放池的使用
//ios5.0新方式
@autoreleasepool
{
//池的區域
}
//ios5.0以前的老方式
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
//池的區域
[pool release];
自動釋放池使用技巧:
PS:已重寫person.m的delloc方法,並在裏面寫上NSLog(@"person對象已釋放");若是delloc方法執行,便會有輸出。
int main(){ //在MRC中並非將ARC的代碼放在池中便可以自動管理內存,每建立一個對象都有在後面加上autorelease NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init]; //不加autorelease,出池後person.m的delloc方法不會執行 Person *person = [[Person alloc]init]; [pool release]; }
此時控制檯輸出:
Program ended with exit code: 0
int main(){ //在MRC中並非將ARC的代碼放在池中便可以自動管理內存,每建立一個對象都有在後面加上autorelease NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init]; //建立對象時在後面加上autorelease,出池後,person.m裏delloc方法執行 Person *person = [[[Person alloc]init] autorelease]; [pool release]; }
此時控制檯輸出:
2015-11-29 14:55:02.287 Test[2757:93300] person對象被釋放 Program ended with exit code: 0
以上是我的看法,如有錯誤歡迎指正,在學習中如有不理解歡迎騷擾 QQ:2314858225