Runtime 總結筆記`深入理解Category`

參考文章美團技術博客

文章爲原創,轉載請註明出處

Category簡介

使用Category把類分開在幾個不同的文件裏,這樣做有幾個好處
  1. 減少單個文件體積
  2. 把不同的功能組織到不同的Category裏
  3. 可以由多個開發者共同完成一個類
  4. 可按需加載要用的Category
  • Category還可以模擬多繼承,把frameWork的私有方法分開
  • Category無法添加實例變量
Category 的結構
  • Objective-C類和對象在runtime都是用結構體表示的,Category也一樣,在runtime層,Category使用category_t結構體
typedef struct category_t {
	const char *name;
	classref_t cls;
	
	struct method_list_t *instanceMethods;
	struct method_list_t *classMethods;
	struct protocol_list_t *protocols;
	struct property_list_t *instanceProperties;
} category_t;

其中包含了:
1. 類的名字
2. 類
3. category中添加的實例方法列表
4. category中添加的類方法列表
5. category中所實現的protocol表列
6. category中添加的屬性

從上面看出Category可以添加(實例方法,類方法,實現協議,添加屬性),不能添加實例變量

Category的加載
  1. Category是在runtime進入入口的時候添加到類上面的,runtime遍歷Category_t數組,將Category的實例方法,協議,屬性添加到類上,把Category的類方法添加到類的metaClass上面
  2. Category方法沒有“完全替換“原來類已有的方法,也就是說,如果Category添加了MethodA,原來的類也有同樣的方法,那麼該類此時有兩個MethodA方
  3. Category的方法被放到了新方法列表的前面,在runtime的objc_msgSend查找方法時,找到第一個方法就調用該方法,所以當多個Category重寫了同一個方法時,會使用編譯時放在後面的Category的方法
Category和+load方法
  1. Category可以覆寫類的+load方法,因爲類的+load發生在Category的+load方法之前,當多個Category都覆寫了+load方法時,Category的+load方法取決於Category文件的編譯順序
Category 和 關聯對象

由於Category中無法動態的添加實例變量,所以可以通過關聯對象的方法來爲類添加實例變量

關聯對象存儲在一個全局叫AssociationsManager的map裏,其中key是被關聯對象的指針地址,value存儲着另一個靜態的全局map,稱爲AssociationHashMap,這裏的key和value分別是設置關聯對象時候的Key和Value

class-continuation

  1. 不對外公開的方法和實例變量寫在"class-continuation"裏,class-continuation只能定義在類的實現文件裏
  2. 屬性和實例方法也可以定義在這裏,定義在這裏然後在依次實現會顯得明確一點
  3. 將public接口實現的只讀方法在這裏擴展成可讀寫方法,以便在內部設置其值,一般不直接訪問實例變量,通過設置方法來做,這樣可以觸發KVO
  4. 對象的協議方法只用設置爲私有時在class-continuation裏定義
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章