分類 擴展 關聯對象
思路
- 做了哪些事情?
- 特點
- 侷限性
- 源碼分析
1. 概述:
不知道源碼的情況下爲類添加方法,可在現有的類的基礎上添加新的方法。
2. 主要作用
- 分解體積大的類文件
- 聲明私有方法
- 把Framework的私有方法公開
- 模擬多繼承
3. 底層實現
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;
// Fields below this point are not always present on disk.
struct property_list_t *_classProperties;
method_list_t *methodsForMeta(bool isMeta) {
if (isMeta) return classMethods;
else return instanceMethods;
}
property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
};
從category結構可以看出:
- 可以添加實例方法,類方法,協議,添加實例屬性,類屬性(但這裏的屬性不會自動生成實例變量和對應的get,set方法,需要通過關聯對象來實現)
- 不可以添加實例變量
加載調用棧
_objc_init ->map_2_images 鏡像->map_images_nlock ->
_read_images->remethodizeClass
把category的實例方法、協議以及屬性添加到類上
把category的類方法和協議添加到類的metaclass上
說明:
在remethodizeClass內部核心方法是:attachCategories
attachLists: 將含有mcount個元素 的mlists拼接到rw的methods上
特點:
運行時決議
可爲系統類添加分類
多總結 多看源碼
關聯對象
提供了以下API:
// 1. 添加關聯對象
void objc_setAssociatedObject(id object, const void* key, id value, objc_AssociationPolicy policy)
// 2. 獲得關聯對象
id objc_getAssociatedObject(id object, const void* key)
// 3. 移除所有的關聯對象
void objc_removeAssociatedObjects(id object)
其中policy屬性,是一個枚舉值,常見修飾詞。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LoD0y0l3-1578018300136)(media/15779461828350/15779542321735.jpg)]
關聯對象底層實現依賴四個核心對象:
AssocationManager
AssocationHashMap
objectAssociationMap
ObjectAssociation
AssocationManager裏面存儲着某個對象的關聯對象Map表,即ObjectAssociationMap,這個表存儲了多個關聯對象,objectAssociationMap就是我們添加的關聯對象.
實現原理
關聯本質
AssociationManager管理並在AssociationHashMap存儲
所有對象的關聯內容都在統一全局容器中。
擴展
定義:
Extension是Category的一個特例,類擴展與分類只少了分類的名稱,所以又稱之爲匿名分類。
作用 :
- 聲明私有屬性
- 聲明私有方法
- 聲明私有成員變量
特點:
編譯時決議
只以聲明的形式存在,多數情況下寄生於宿主類中,不能爲系統類添加擴展
特點:
- 編譯時決議
- 不能爲系統類添加擴展
因爲運行期,對象的內部佈局已經確定,如果添加實例變量會破壞類的內部佈局,這對編譯性語言是災難性的。