RunTime之消息轉(zhuǎn)發(fā)

消息

在Objective-C中,消息是直到運(yùn)行的時(shí)候才和方法實(shí)現(xiàn)綁定的。消息機(jī)制的關(guān)鍵在于編譯器為類和對(duì)象生成的結(jié)構(gòu)。每個(gè)類的結(jié)構(gòu)中至少包括兩個(gè)基本元素:

(1) 指向父類的指針
(2)類的方法表。方法表將方法選標(biāo)和該類的方法實(shí)現(xiàn)的地址關(guān)聯(lián)起來。
消息框架如下

消息框架.png

消息轉(zhuǎn)發(fā)

當(dāng)向someObject發(fā)送消息,但runtime system在當(dāng)前類和父類中都找不到對(duì)應(yīng)的方法實(shí)現(xiàn)時(shí)。runtime system并不會(huì)立即報(bào)錯(cuò)使程序崩潰,而是依次執(zhí)行下列步驟:

步驟.png

分別簡(jiǎn)述一下流程:
(1) 動(dòng)態(tài)方法解析 向當(dāng)前類發(fā)送 resolveInstanceMethod: 或者 resolveClassMethod: 消息,檢查是否動(dòng)態(tài)向該類添加了方法。
(2)快速消息轉(zhuǎn)發(fā) 檢查該類是否實(shí)現(xiàn)了forwardingTargetForSelector: 方法,若實(shí)現(xiàn)了則調(diào)用該方法。若該方法返回值對(duì)象非nil或非self,則向該返回對(duì)象重新發(fā)送消息。
(3)標(biāo)準(zhǔn)消息轉(zhuǎn)發(fā) runtime發(fā)送methodSignatureForSelector:方法獲取Selector對(duì)應(yīng)的方法簽名。返回值非nil則通過forwardInvocation:轉(zhuǎn)發(fā)消息,返回值為nil則向當(dāng)前對(duì)象發(fā)送doesNotRecognizeSelector:消息,程序崩潰退出。

示例

示例界面如下

示例主界面.png
#pragma mark - event response
- (void)dynamicBtnClicked:(id)sender
{
    self.dianDi86.name = @"DianDi86";
    NSLog(@"%@",self.dianDi86.name);
}

- (void)fastForwardBtnClicked:(id)sender
{
    [self.whiteHouse performSelector:@selector(setSex:) withObject:@"Boy"];
}

- (void)normalForwardBtnClicked:(id)sender
{
    [self.audioA4L performSelector:@selector(setSex:) withObject:@"Boy"];
}

動(dòng)態(tài)方法解析

#import "People.h"
#include <objc/runtime.h>

void dynamicSetNameIMP(id self, SEL _cmd, NSString *name)
{
    NSLog(@"%@ %@",self, NSStringFromSelector(_cmd));
    
    if (((People*)self)->_name != name) {
        ((People*)self)->_name = [name copy];
    }
}

NSString* dynamicNameIMP(id self, SEL _cmd)
{
    NSLog(@"%@ %@",self, NSStringFromSelector(_cmd));
    return ((People*)self)->_name;
}

@implementation People

@dynamic name;

+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    if (sel == @selector(setName:)) {
        class_addMethod(self, sel, (IMP)dynamicSetNameIMP, "v@:@");
        
        return YES;
    } else if (sel == @selector(name)) {
        class_addMethod(self, sel, (IMP)dynamicNameIMP, "@@:");
        
        return YES;
    }
    
    return [super resolveInstanceMethod:sel];
}

@end

點(diǎn)擊示例界面中的動(dòng)態(tài)方法解析console log 如下

動(dòng)態(tài)解析.png

快速消息轉(zhuǎn)發(fā)

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    // House 類需要將消息轉(zhuǎn)發(fā)給People
    NSLog(@"%@ %@",self, NSStringFromSelector(_cmd));
    if ([self.master respondsToSelector:aSelector]) {
        return self.master;
    }
    
    return nil;
}

點(diǎn)擊示例界面中的快速消息轉(zhuǎn)發(fā)console log 如下

快速消息轉(zhuǎn)發(fā).png

標(biāo)準(zhǔn)消息轉(zhuǎn)發(fā)

- (NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector
{
    NSLog(@"%@ %@",self, NSStringFromSelector(_cmd));
    NSMethodSignature *sign = [super methodSignatureForSelector:aSelector];
    if (sign == nil) {
        sign = [self.master methodSignatureForSelector:aSelector];
    }
    
    return sign;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    NSLog(@"%@ %@",self, NSStringFromSelector(_cmd));
    SEL selector = [anInvocation selector];
    if ([self.master respondsToSelector:selector]) {
        [anInvocation invokeWithTarget:self.master];
    }
    
}

點(diǎn)擊示例界面中的快速消息轉(zhuǎn)發(fā)console log 如下

標(biāo)準(zhǔn)消息轉(zhuǎn)發(fā).png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 最近開始學(xué)習(xí)Runtime相關(guān)的內(nèi)容.之前的話知道OC是一門動(dòng)態(tài)的語(yǔ)言(動(dòng)態(tài)類型,動(dòng)態(tài)綁定,動(dòng)態(tài)加載),卻不知道到...
    kikido閱讀 1,891評(píng)論 0 1
  • Objective-C runtime之消息轉(zhuǎn)發(fā)機(jī)制(三) 作者:wangzz原文地址:http://blog.c...
    飄搖的水草閱讀 355評(píng)論 0 0
  • 概要 runtime是Objective-C的動(dòng)態(tài)機(jī)制。runtime執(zhí)行的是編譯后的代碼,這時(shí)它可以動(dòng)態(tài)加載對(duì)象...
    NapoleonY閱讀 245評(píng)論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,578評(píng)論 19 139
  • 一 太陽(yáng)城是一座夢(mèng)想之城,動(dòng)物們追隨著夢(mèng)想的腳步,棲息于此,歡樂于此,但有時(shí),也不免痛苦于此。歡樂之時(shí),他們說這座...
    阿秋的冬天閱讀 1,268評(píng)論 0 0

友情鏈接更多精彩內(nèi)容