Catergory
在編譯時,會將分類生成一個category_t結構體
分類的本質:runtime會將分類中的方法、協議、屬性分別拼接成3個數組,且分類方法、協議、屬性的順序和分類的編譯順序有關,后編譯的會在前面。然后回將生成的數組進行momerymove(內存移動)操作,拼接在類對象和元類對象的rw->method_list等屬性的最前面
分類源碼調用順序:
在pobjc-os.mm文件中
_objc_init?
map_images
map_images_nolock
在pobjc-runtime-new.mm 文件中
_read_images
remethodizeClass
attachCategories
attachLists
realloc、memmove、 memcpy
+load方法
調用時機:會在runtime加載類和分類時調用,且只調用一次。
調用順序:分類的+ load方法和類的 + load方法都會調用,且一定是原類中的load方法先調用,因為在源碼中,會先找到原類中的+ load方法的內存地址,直接單獨調用,再按照分類文件的編譯順序進行分別調用分類中的+ load方法,先編譯的先調用。
源碼調用順序:?
+initialize方法
調用時機:+initialize方法,是在類第一次調用objc_msgSend方法前調用,即類第一次接收到消息前調用
調用順序:+initialize方法在源碼中,先判斷當前類是否調用過+initialize(initialized);如果沒有調用過,則會通過遞歸的方法尋找其父類的+initialize方法;接下來會判斷當前父類是否initialized,如果父類沒有調用過則父類先調用callInitialize即調用+initialize方法,再進行調用子類的+initialize方法。
源碼調用順序:
在pobjc-msg-arm64.s文件中
objc_msgSend
在pobjc-runtime-new.mm文件中
class_getInstanceMethod
lookUpImpOrNil
lookUpImpOrForward
_class_initialize
callInitialize
objc_msgSend(cls, SEL_initialize)
區別:
1)+initialize方法是通過objc_msgSend方法調用,與load方法的直接通過地址指針進行調用不同
2)如果子類沒有調用+initialize方法,且子類不存在+initialize方法,則會調用父類的+initialize方法,因此父類的+initialize方法有可能會調用多次
3)因為+initialize方法是通過objc_msgSend方法調用,因此分類的+initialize方法會覆蓋本身的+initialize方法