如今你們的項目應該基本都是ARC了,若是仍是MRC的話,趕忙轉換到ARC吧!最近被臨時拉過去開發iPad,因爲項目緣由,仍是使用的MRC。今天在調部分界面的時候,發現一段代碼,我怎麼看都怎麼以爲怪怪的,由於是MRC嘛!因此我內心仍是一直提醒着本身。仔細一看還真是不對,這段代碼給周圍同事看的時候,也不是每一個人都能一眼看出問題,由於你們已經習慣了ARC或者沒有在MRC下進行開發過。指針
下面我貼出相似的代碼:code
- (void)pushVc { pushVC = [[UIViewController alloc] init]; [self.navigationController pushViewController:pushVC animated:YES]; }
以上這段代碼很簡單,就是有個UIViewController類型的成員變量pushVC
,而後建立一個VC賦值給他,最後push到這個頁面。可能不少人一看,這代碼就是日常本身寫的啊,都沒有出現過問題啊。若是這段代碼是在ARC下,是沒有任何問題的。可是,若是咱們的代碼是在MRC下,會出現什麼問題呢?若是經歷過MRC開發的人,確定也會以爲這邊怪怪的。至少沒有發現調用release
。因爲pushVC
是成員變量,因此必定程度上也迷惑了下同事。上面的代碼其實已經內存泄露了。[[UIViewController alloc] init]
這個方法建立出來的對象將不會被銷燬,一直留在內存中。爲何?這個對象建立出來的時候引用是1,而後通過push
引用計數已經變成2了。當這個vc在後面被pop
出來的時候,引用計數會減1,這時這個VC的引用計數仍是1。在內存中將銷燬不掉。若是這個方法被屢次調用的話,將會出現大量的這個對象在內存中。對象
下面再說一個知識點,不少人知道,可是並不必定徹底瞭解咱們的@property
到底作了什麼。內存
- (void)pushVc { self.pushVC = [[UIViewController alloc] init]; [self.navigationController pushViewController:pushVC animated:YES]; }
在看這段代碼,我給成員變量賦值的方式換成了self.pushVC
,這個和直接賦值有什麼區別呢?若是你調用self.pushVC
進行賦值,那麼這個時候會調用系統爲咱們默認生成的setter
方法。這個setter會幫咱們作內存的引用計數操做。看下系統生成的方法示例:開發
- (void)setPushVC:(UIViewController *)setPushVC { [setPushVC retain]; [pushVC release]; pushVC = setPushVC; }
首先,系統會將傳進來的對象引用計數加1,以後將賦值的對象引用計數減1,最後再給對象賦值。記得本身重寫setter
方法的時候,必定要先將傳進來的對象作下retain
操做,以後在release
自己的對象。若是你代碼這樣寫的話:編譯器
- (void)setPushVC:(UIViewController *)setPushVC { [pushVC release]; [setPushVC retain]; pushVC = setPushVC; }
正常狀況下是沒有問題的,可是若是是本身給本身賦值的話self.pushVC = pushVC
,那就有問題了。固然你能夠作下if判斷,兩個對象是否同樣,那樣也行。it
接下來看下這個代碼的正確寫法:內存管理
UIViewController *VC = [[UIViewController alloc] init]; pushVC = [VC retain]; [VC release]; [self.navigationController pushViewController:VC animated:YES]; //或者 UIViewController *VC = [[UIViewController alloc] init]; self.pushVC = VC [VC release]; [self.navigationController pushViewController:VC animated:YES];
建議你們在MRC下使用成員變量的時候最好使用self.
setter方法。有同事又提出了另外一種寫法:io
pushVC = [[[UIViewController alloc] init] autorelease]; [self.navigationController pushViewController:pushVC animated:YES];
用autorelease
,可是這樣寫有個問題,一旦你使用這個關鍵字,那你就不在有這個建立對象的內存管理權,系統會在以後的某個時間,對其進行release
操做。這樣也違背了用成員變量保存這個VC的意圖。編譯
不少同事一眼沒有看出來,是由於咱們已經習慣了ARC,認爲=
就是給對象進行了retain
。在ARC下默認變量前面都有一個隱藏的__strong
。在ARC下只要變量指向對象,那麼系統會咱們自動的對那個對象進行retain
操做,當咱們將對象置爲nil
的時候,系統會默認給咱們作release
操做。
引用計數內存管理的思考方式:
- 本身生成的對象,本身所持有
當咱們使用ARC的時候,也是遵循了上面的思考方式。不要由於咱們沒有看到retain
或者release
而認爲管理方式變了或者不須要內存管理了。ARC看起來很簡單,由於蘋果把那些引用計數的操做代碼都交給了編譯器,因此給了咱們這種錯覺。瞭解MRC,能夠加深本身對ARC的理解。不至於讓本身被ARC給矇蔽了。
使用ARC可讓咱們的代碼更加精簡,健壯,特別是weak
這個關鍵字,更是解決了野指針的問題。