分類中的方法是通過runtime動(dòng)態(tài)的將分類的方法合并到類對象腺劣,元類對象中的沛贪。也就是在程序運(yùn)行過程中合并的怕午,不是編譯時(shí)合并的废登。
分類里面的方法一開始(也就是編譯完畢的時(shí)候)是存在上圖這個(gè)結(jié)構(gòu)里面堡距。等一下就會利用運(yùn)行時(shí)機(jī)制,將這個(gè)結(jié)構(gòu)體里面的方法合并到類對象里面去(類方法就合并到元類對象里面去)兆蕉。
編寫一個(gè)分類會產(chǎn)生一個(gè)struct _category_t對象羽戒,在編寫另一個(gè)分類的話,就會產(chǎn)生另一個(gè)新的struct _category_t對象
每一個(gè)分類都會生成一個(gè)struct _category_t的結(jié)構(gòu)體
上圖就是核心方法虎韵,static void remethodizeClass(Class cls) 重新組織cls的方法(cls可能是類對象易稠,也可能是元類對象)----也就是類對象的對象方法列表(元類對象的類方法列表)可能重新組織下,可能往里面加?xùn)|西包蓝。
attachCategories(cls,cats)--(attach附加的意思)這個(gè)方法的意思就是把分類的信息附加到類對象里面去
memmove --內(nèi)存移動(dòng) memcpy -- 內(nèi)存拷貝
rw ->methods --原來類的方法列表(圖中其箭頭所指的方向是其里面的數(shù)據(jù)驶社,也就是具體方法)
這樣過后企量,分類里面的方法就合并到對應(yīng)類的方法列表中去了。
過程就是:首先通過傳進(jìn)來的方法列表大小衬吆,將類的方法列表擴(kuò)容梁钾,并把類原來的方法列表挪到最后面去,再把傳進(jìn)來的方法列表加進(jìn)去逊抡。
如果一個(gè)類的兩個(gè)分類中姆泻,都有同一個(gè)方法。那么調(diào)用該方法時(shí)冒嫡,哪個(gè)分類后被編譯就先調(diào)用哪個(gè)分類的里面的方法拇勃。(調(diào)用一個(gè)對象A方法時(shí),通過isa去類的對象方法列表中查找相應(yīng)的A方法孝凌,找到A方法后方咆,立馬返回,就不會再去找了蟀架。所以分類的方法覆蓋是假的覆蓋瓣赂,原來的方法還是在的,只是排在分類的方法后面了片拍,所以出現(xiàn)假覆蓋的現(xiàn)象)煌集。
最后面參與編譯的分類優(yōu)先放到前面,所以優(yōu)先調(diào)用最后參與編譯的分類的里面的方法捌省。
上圖中先編譯分類eat,在編譯mjperson,最后編譯test苫纤。
上圖中,類擴(kuò)展中的屬性纲缓,方法卷拘,一編譯的時(shí)候就已經(jīng)存在于我們的類對象中,跟分類是不一樣的祝高。
分類的本質(zhì):編譯完畢的時(shí)候栗弟,分類都是獨(dú)立存在的,大家都是那個(gè)結(jié)構(gòu)體工闺,但是程序一旦運(yùn)行的話横腿,運(yùn)行時(shí)機(jī)制就會將每一個(gè)獨(dú)立的分類的所有數(shù)據(jù)先合并到一起,在插入到類原來數(shù)據(jù)的前面斤寂。