~ Category的實(shí)現(xiàn)原理?
Category編譯之后的底層結(jié)構(gòu)是struct category_t (struct結(jié)構(gòu)體),里面存儲著分類的對象方法、類方法、屬性、協(xié)議信息,在程序運(yùn)行的時候,runtime會將Category的數(shù)據(jù),合并到類信息中。(類對象、元類對象中)
~ Category和Class Extension的區(qū)別是什么?(Extension擴(kuò)展)
Class Extension在編譯的時候,它的數(shù)據(jù)就已經(jīng)包含在類信息中。
Category是在運(yùn)行時,才會將數(shù)據(jù)合并到類信息中。
(Extension可以添加方法和屬性。類擴(kuò)展不能像類別那樣擁有獨(dú)立的實(shí)現(xiàn)部分(@implementation部分),也就是說,類擴(kuò)展所聲明的方法必須依托對應(yīng)類的實(shí)現(xiàn)部分來實(shí)現(xiàn)。
。Category只能添加方法。但是OC語言有動態(tài)性,在runtime。只要我們手動在運(yùn)行時的時候,間接實(shí)現(xiàn)Category有成員變量的效果)
~ Category中有l(wèi)oad方法嗎?load方法是什么時候調(diào)用的?load 方法能繼承嗎?
有l(wèi)oad方法。
load方法在runtime加載類、分類的時候調(diào)用。
load方法可以繼承,但是一般情況下不會主動去調(diào)用load方法,都是讓系統(tǒng)自動調(diào)用。
~ +load方法
+load方法會在runtime加載類、分類時調(diào)用。
每個類、分類的+load,在程序運(yùn)行過程中只調(diào)用一次。
~ +initialize方法
+initialize方法會在類第一次接收消息時調(diào)用。
先初始化父類,再初始化子類,每個類只初始化一次。
~ +initialize方法和+load方法的區(qū)別?
+initialize方法是通過objc_msgSend進(jìn)行調(diào)用。
如果子類沒有實(shí)現(xiàn)+initialize方法,就會調(diào)用父類的+initialize方法(所以父類會調(diào)用多次)
~ 怎么實(shí)現(xiàn)Category的成員變量?
因?yàn)榉诸惖讓咏Y(jié)構(gòu)限制,不能添加成員變量到分類中。但可以通過關(guān)聯(lián)對象來間接實(shí)現(xiàn)。
關(guān)聯(lián)對象提供的API
添加關(guān)聯(lián)對象
void objc_setAssociatedObject(id object, const voidkey, id value, objc_AssociationPolicy policy)
獲得關(guān)聯(lián)對象
id objc_getAssociatedObject(id object, const voidkey)
移除所有關(guān)聯(lián)對象
void objc_removeAssociatedObjects(id object)