淺談iOS記憶體管理機制,淺談ios記憶體管理

來源:互聯網
上載者:User

淺談iOS記憶體管理機制,淺談ios記憶體管理

      iOS記憶體管理機制的原理是引用計數,引用計數簡單來說就是統計一塊記憶體的所有權,當這塊記憶體被建立出來的時候,它的引用計數從0增加到1,表示有一個對象或指標持有這塊記憶體,擁有這塊記憶體的所有權,如果這時候有另外一個對象或指標指向這塊記憶體,那麼為了表示這個後來的對象或指標對這塊記憶體的所有權,引用計數加1變為2,之後若有一個對象或指標不再指向這塊記憶體時,引用計數減1,表示這個對象或指標不再擁有這塊記憶體的所有權,當一塊記憶體的引用計數變為0,表示沒有任何對象或指標持有這塊記憶體,系統便會立刻釋放掉這塊記憶體。

      其中在開發時引用計數又分為ARC(自動記憶體管理)和MRC(手動記憶體管理)。ARC的本質其實就是MRC,只不過是系統協助開發人員管理已建立的對象或記憶體空間,自動在系統認為合適的時間和地點釋放掉已經失去作用的記憶體空間,原理是一樣的。雖然ARC操作起來很方便,不但減少了代碼量,而且降低了記憶體出錯的機率,但因為ARC不一定會及時釋放,所以程式有時候可能會佔用記憶體較大。而MRC若做得好,通過手動管理,及時釋放掉不需要的記憶體空間,便可保證程式長時間運行在良好狀態上。

     在MRC中會引起引用計數變化的關鍵字有:alloc,retain,copy,release,autorelease。(strong關鍵字只用於ARC,作用等同於retain)

     alloc:當一個類的對象建立,需要開闢記憶體空間的時候,會使用alloc,alloc是一個類方法,只能用類調用,它的作用是開闢一塊新的記憶體空間,並使這塊記憶體的引用計數從0增加到1,注意,是新的記憶體空間,每次用類alloc出來的都是一塊新的記憶體空間,與上一次alloc出來的記憶體空間沒有必然聯絡,而且上一次alloc出來的記憶體空間仍然存在,不會被釋放。

     retain:retain是一個執行個體方法,只能由對象調用,它的作用是使這個對象的記憶體空間的引用計數加1,並不會新開闢一塊記憶體空間,通常於賦值是調用,如:

對象2=[對象1 retain];表示對象2同樣擁有這塊記憶體的所有權。若只是簡單地賦值,如:對象2=對象1;那麼當對象1的記憶體空間被釋放的時候,對象2便會成為野指標,再對對象2進行操作便會造成記憶體錯誤。

     copy:copy同樣是一個執行個體方法,只能由對象調用,返回一個新的對象,它的作用是複製一個對象到一塊新的記憶體空間上,舊記憶體空間的引用計數不會變化,新的記憶體空間的引用計數從0增加到1,也就是說,雖然內容一樣,但實質上是兩塊記憶體,相當於複製,一個變成兩個。其中copy又分為淺拷貝、深拷貝和真正的深拷貝,淺拷貝只是拷貝地址與retain等同;深拷貝是拷貝內容,會新開闢新記憶體,與retain不一樣;真正的深拷貝是對於容器類來說的,如數組類、字典類和集合類(包括可變和不可變),假設有一個數組類對象,普通的深拷貝會開闢一塊新記憶體存放這個對象,但這個數組對象裡面的各個元素的地址卻沒有改變也就是說數組元素只是進行了retain或者淺拷貝而已,並沒有建立新的記憶體空間,而真正的深拷貝,不但數組對象本身進行了深拷貝,連數組元素都進行了深拷貝,即為各個數組元素開闢了新的記憶體空間。

     release:release是一個執行個體方法,同樣只能由對象調用,它的作用是使對象的記憶體空間的引用計數減1,若引用計數變為0則系統會立刻釋放掉這塊記憶體。如果引用計數為0的基礎上再調用release,便會造成過度釋放,使記憶體崩潰;

     autorelease:autorelease是一個執行個體方法,同樣只能由對象調用,它的作用於release類似,但不是立刻減1,相當於一個延遲的release,通常用於方法傳回值的釋放,如便利構造器。autorelease會在程式走出自動釋放池時執行,通常系統會自動產生自動釋放池(即使是MRC下),也可以自己設定自動釋放池,如:

@autoreleasepool{

obj= [[NSObject alloc]init];

[obj autorelease];

}

當程式走出“}”時obj的引用計數就會減1.

      除了以上所述的關鍵字,還有一些方法會引起引用計數的變化,如UI中父視圖添加、移除子視圖,導航控制器或視圖控制器推出新的視圖控制器以及返回,容器類(數組、字典和集合)添加和移除元素。

      當子視圖添加到父視圖上時,子視圖的引用計數加1,移除時引用計數減1,若父視圖引用計數變為0記憶體被釋放,其所有的子視圖都會被release一次,即引用計數減1,原則上只有這三種情況子視圖的引用計數會發生變化,其他如父視圖引用計數的加減都不會影響到子視圖。

      容器類的情況與視圖類似,添加元素,該元素引用計數加1,移除元素,該元素引用計數減1,容器引用計數變為0所佔用記憶體被釋放,容器所有元素release,引用計數減1,其他情況下容器本身的引用計數變化不會影響到容器內元素的引用計數變化。

      導航控制器或視圖控制器推出新的視圖控制器會使被推出的視圖控制器的引用計數加1,該視圖控制器返回的時候引用計數減1,具體方法如下:

導航控制器推出視圖控制器調用方法:- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;

返回時同樣用導航控制器調用方法:- (UIViewController *)popViewControllerAnimated:(BOOL)animated;

視圖控制器推出視圖控制器調用方法:- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion

返回時被推出的視圖控制器調用方法:- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion

      應注意:當一個對象的引用計數變為0佔用記憶體被釋放時,會調用- (void)dealloc方法,所以如果在MRC下自訂類,必須在該方法裡將該類中屬性關鍵字設定為retain或copy的屬性release一次,以免造成記憶體泄露,重寫方法不要忘記在第一行添加[super dealloc];。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.