1.方法歸屬
自定義類一個實例方法和一個類方法


main函數(shù)調(diào)用

lgObjc_copyMethodList 函數(shù):用于獲取類的方法列表

lgInstanceMethod_classToMetaclass 函數(shù):用于獲取類的實例方法

lgClassMethod_classToMetaclass 函數(shù):用于獲取類的類方法

lgIMP_classToMetaclass 函數(shù):用于獲取方法的實現(xiàn)

打印結(jié)果

解析:
lgObjc_copyMethodList函數(shù) 分析
在這個函數(shù)中,主要是獲取LGPerson類中的方法列表,從實例方法存儲在類中,類方法存儲在元類中可以得知,LGPerson的方法列表打印結(jié)果只有sayHello方法
lgInstanceMethod_classToMetaclass?函數(shù) 分析
從上面代碼可知,傳入的pclass?是類LGPerson,通過objc_getMetaClass獲取的LGPerson的元類 是元類LGPerson,函數(shù)中4個打印結(jié)果分別是:
method1?地址:0x1000031b0
傳入的pClass是LGPerson類,需要去獲取selName = sayHello的實例方法
首先在LGPerson中查找,有前面的LGPerson類可知,是有這個實例方法的,所以會返回查找到的實例方法,所以method1的地址不為0x0
method2?地址:0x0
傳入的pClass是LGPerson元類,需要去獲取selName = sayHello的實例方法
其查找的順序為元類 --> 根元類 --> 根類 --> nil,直到最后也沒有找到,所以class_getInstanceMethod返回NULL,其method2的地址為0x0,表示未找到
method3?地址:0x0
傳入的pClass是LGPerson類,需要去獲取selName = sayHappy的實例方法
查找順序為LGPerson類 --> 根類 --> nil,也沒有找到sayHappy實例方法,返回NULL,所以method3的地址為0x0,表示未找到
method4?地址:0x100003148
傳入的pClass是LGPerson元類,需要去獲取selName = sayHappy的實例方法
首先在LGPerson元類中查找,發(fā)現(xiàn)有sayHappy的實例方法,主要是因為類對象的類方法存儲在元類中,類方法在元類中是實例方法,然后返回查找到的實例方法,所以method3的地址為0x100003148,表示找到了指定的實例方法
lgClassMethod_classToMetaclass函數(shù)分析
class_getClassMethod


看該方法的源碼實現(xiàn),可以得出class_getClassMethod的實現(xiàn)是獲取類的類方法,其本質(zhì)就是獲取元類的實例方法,最終還是會走到class_getInstanceMethod,但是在這里需要注意的一點是:在getMeta源碼中,如果判斷出cls是元類,那么就不會再繼續(xù)往下遞歸查找,會直接返回this,其目的是為了防止元類的無限遞歸查找
打印結(jié)果有以下分析:
method1 地址:0x0
pClass是LGPerson類,selName是sayHello
首先判斷LGPerson類是否是元類,此時不是,返回LGPerson的元類,然后在元類中查找sayhello實例方法。查找順序如下:元類 --> 根元類 --> 根類 --> nil,最后返回NULL
method2 地址:0x0
metaClass是LGPerson元類,selName是sayHello
首先判斷LGPerson元類是否是元類,此時是,直接返回元類,然后在元類中查找sayhello實例方法,發(fā)現(xiàn)并沒有找到,返回NULL
method3 地址:0x100003148
pClass是LGPerson類,selName是sayHappy
首先判斷LGPerson類是否是元類,此時不是,返回LGPerson的元類,然后在元類中查找sayHappy實例方法,發(fā)現(xiàn)有這個實例方法,直接返回找到的實例方法。
method4 地址:0x100003148
pClass是LGPerson元類,selName是sayHappy
首先判斷LGPerson元類是否是元類,此時是,直接返回元類,然后在元類中查找sayHappy實例方法,發(fā)現(xiàn)有這個實例方法,直接返回找到的實例方法
lgIMP_classToMetaclass函數(shù) 分析
該函數(shù)在向類實例發(fā)送消息時會被調(diào)用,并返回一個指向方法實現(xiàn)函數(shù)的指針。這個函數(shù)會比method_getImplementation(class_getInstanceMethod(cls, name))更快。返回的函數(shù)指針可能是一個指向runtime內(nèi)部的函數(shù),而不一定是方法的實際實現(xiàn)。如果類實例無法響應(yīng)selector,則返回的函數(shù)指針將是運行時消息轉(zhuǎn)發(fā)機制的一部分
class_getMethodImplementation

4個打印結(jié)果:
imp1 函數(shù)指針地址:0x100001d00
pClass?是?LGPerson類,sel?是?sayHello
根據(jù)LGPerson文件,可以得出LGPerson類中可以查找到sayHello的具體實現(xiàn),所以返回一個imp函數(shù)指針的地址
imp2 函數(shù)指針地址:0x7fff66238d80
pClass是LGPerson元類,sel是sayHello
根據(jù)類方法存儲在元類中可知,sayHello是一個實例方法,并不存儲在元類中,也沒有其任何實現(xiàn),所以進行了消息轉(zhuǎn)發(fā)
mp3 函數(shù)指針地址:0x7fff66238d80
pClass是LGPerson類,sel是sayHappy
根據(jù)LGPerson文件,sayHappy是一個類方法,并不存儲在類中,也沒有其任何實現(xiàn),所以進行了消息轉(zhuǎn)發(fā)
imp4 函數(shù)指針地址:0x100001d30
pClass是LGPerson元類,sel是sayHappy
根據(jù)類方法存儲在元類文件,可以在元類中查找到sayHappy的具體實現(xiàn),所以返回一個imp函數(shù)指針的地址
總結(jié)
class_getInstanceMethod:獲取實例方法,如果指定的類或其父類不包含帶有指定選擇器的實例方法,則為NULL
class_getClassMethod:獲取類方法,如果指定的類或其父類不包含具有指定選擇器的類方法,則為NULL。
class_getMethodImplementation:獲取方法的具體實現(xiàn),如果未查找到,則進行消息轉(zhuǎn)發(fā)
2.isKindOfClass 和 isMemberOfClass
先上問題和答案~~


先分析方法源碼


isKindOfClass
類方法:元類 --> 根元類 --> 根類 --> nil?與?傳入類的對比
實例方法:對象的類 --> 父類 --> 根類 --> nil?與?傳入類的對比
isMemberOfClass
類方法:?類的元類?與?傳入類?對比
實例方法:對象的父類?與?傳入類?對比
根據(jù)源碼的分析,來分析代碼執(zhí)行結(jié)果
re1 :1 ,是NSObject與NSObject的對比,使用+isKindOfClass
NSObject(傳入類,即根類) vs NSObject的元類即根元類-- 不相等
NSObject(傳入類,即根類) vs 根元類的父類即根類-- 相等,返回1
re2 :0 ,是NSObject與NSObject的對比,使用+isMemberOfClass
NSObject根類(傳入類) vs NSObject的元類即根元類-- 不相等
re3 :0 ,是LGPerson與LGPerson的對比,使用+isKindOfClass
LGPerson(傳入類) vs LGPerson的元類即元類LGPerson? -- 不相等
LGPerson(傳入類) vs 元類LGPerson的父類即根元類-- 不相等
LGPerson(傳入類) vs 根元類的父類即根類-- 不相等
LGPerson(傳入類) vs 根類的父類即nil-- 不相等
re4 :0 ,是LGPerson與LGPerson的對比,使用+isMemberOfClass
LGPerson(傳入類) vs元類-- 不相等
使用實例方法結(jié)果解析
re5 :1 ,是NSObject對象與NSObject的對比,使用-isKindOfClass
NSObject(傳入類,即根類) vs 對象的類即NSObject根類 -- 相等
re6 :1 ,是NSObject對象與NSObject的對比,使用-isMemberOfClass
NSObject(傳入類,即根類) vs 對象的類即NSObject根類 -- 相等
re7 :1 ,是LGPerson對象與LGPerson的對比,使用-isKindOfClass
LGPerson(傳入類) vs 對象的類即LGPerson -- 相等
re8 :1 ,是LGPerson對象與LGPerson的對比,使用-isMemberOfClass
LGPerson(傳入類) vs 對象的類即LGPerson -- 相等