一個對象的方法像這樣[obj foo]
,編譯器轉成消息發送objc_msgSend(obj, foo),objec_msgSend的方法定義以下:
函數
OBJC_EXPORT id objc_msgSend(id self, SEL op, ...)
spa
isa
找到它的類。method_list
,是否有selector
方法。method_list
。method
,執行它的IMP
。IMP
的return
值。咱們看看對象(object),類(class),方法(method)這幾個的結構體:指針
isa
指針指向類對象,
isa
指針指向的結構體建立,類對象的isa
指針指向的咱們稱之爲元類(metaclass
),元類的isa
指針又指向了本身。
SEL originalSelector = @selector(viewDidLoad);
Method originalMethod = class_getInstanceMethod(class,originalSelector);
class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
method_exchangeImplementations(originalMethod, swizzledMethod);
class_getMethodImplementation(objc_getMetaClass("A"),SEL name);//獲取類方法的實現
class_getMethodImplementation(objc_getClass("A"),SEL name);//獲取實例方法的實現
Method class_getClassMethod(Class cls, SEL name);//獲取類方法的方法體
Method class_getInstanceMethod(Class cls, SEL name);//獲取實例方法的方法體
IMP method_getImplementation(Method m);//根據方法體
獲取IMP地址
IMP method_getImplementation(Method m);//根據方法體
Method
和咱們平時理解的函數是一致的,就是表示可以獨立完成一個功能的一段代碼,
selector
就是個映射到方法的
C
字符串,你能夠用
Objective-C
編譯器命令
@selector()
或者
Runtime
系統的
sel_registerName
函數來得到一個
SEL
類型的方法選擇器。
的定義就是指向最終實現程序的內存地址的指針。
消息轉發完整流程:
_objc_msgForward(id receiver,SEL sel, ...) 調用此方法進行消息轉發,即便實現了該方法也會轉發typedef id (*IMP)(id, SEL, ...); IMP
super
關鍵字接收到消息時,編譯器會建立一個
objc_super
結構體:
struct objc_super { id receiver; Class class; };
receiver
仍然是
self
自己,當咱們想經過
[super class]
獲取父類時,編譯器實際上是將指向
self
的
id
指針和
class
的 SEL 傳遞給了
objc_msgSendSuper
函數。只有在
NSObject
類中才能找到
class
方法,而後
class
方法底層被轉換爲
object_getClass()
, 接着底層編譯器將代碼轉換爲
objc_msgSend(objc_super->receiver, @selector(class))
,傳入的第一個參數是指向
self
的
id
指針,與調用
[self class]
相同,因此咱們獲得的永遠都是
self
的類型。