你要知道的runtime都在這里
轉載請注明出處 http://www.lxweimin.com/p/4a32fb8648a3
本文主要講解runtime
相關知識,從原理到實踐,由于包含內容過多分為以下五篇文章詳細講解,可自行選擇需要了解的方向:
- 從runtime開始: 理解面向對象的類到面向過程的結構體
- 從runtime開始: 深入理解OC消息轉發機制
- 從runtime開始: 理解OC的屬性property
- 從runtime開始: 實踐Category添加屬性與黑魔法method swizzling
- 從runtime開始: 深入weak實現機理
本文是系列文章的第五篇文章,也是系列文章的最后一篇從runtime開始: 深入weak實現機理,本文主要講解runtime
是如何實現weak
修飾符的。
weak
修飾符我們一點也不陌生在開發中經常用到,最主要的作用是為了防止引用循環(retained cycle)
,經常用于block
和delegate
,在前面幾篇文章中已經講解了weak
的基本使用和引用循環,如果有興趣可以參考文章iOS @property探究(一): 基礎詳解、iOS @property探究(二): 深入理解、iOS block探究(一): 基礎詳解、iOS block探究(二): 深入理解,相關方法和特點本文不再贅述了。
weak
weak
不論是用作property
修飾符還是用來修飾一個變量的聲明其作用是一樣的,就是不增加新對象的引用計數,被釋放時也不會減少新對象的引用計數,同時在新對象被銷毀時,weak
修飾的屬性或變量均會被設置為nil
,這樣可以防止野指針錯誤,本文要講解的也正是這個特性,runtime
如何將weak
修飾的變量的對象在銷毀時自動置為nil
。
那么runtime
是如何實現在weak
修飾的變量的對象在被銷毀時自動置為nil
的呢?一個普遍的解釋是:runtime
對注冊的類會進行布局,對于weak
修飾的對象會放入一個hash表
中。用weak
指向的對象內存地址作為key
,當此對象的引用計數為0的時候會dealloc
,假如weak
指向的對象內存地址是a
,那么就會以a
為鍵在這個weak表
中搜索,找到所有以a
為鍵的weak
對象,從而設置為nil
。
了解了以上知識后就可以深入runtiem
代碼來看看具體實現細節,有興趣的讀者可以繼續閱讀。
深入runtime理解weak
這部分內容參考《Objective-C高級編程:iOS與OS X多線程和內存管理》,可以看出具體的實現方式就是使用了一個HashTable
。
NSString *name = [[NSString alloc] initWithString: @"Jiaming Chen"];
__weak NSString *weakStr = name;
當為weakStr
這一weak
類型的對象賦值時,編譯器會根據name
的地址為key去查找weak哈希表
,該表項的值為一個數組,將weakStr
對象的地址加入到數組中,當name
變量超出變量作用域或引用計數為0時,會執行dealloc
函數,在執行該函數時,編譯器會以name
變量的地址去查找weak哈希表
的值,并將數組里所有 weak
對象全部賦值為nil。
備注
由于作者水平有限,難免出現紕漏,如有問題還請不吝賜教。