Runtime梳理(三)

挖就挖底層.png

繼上《Runtime梳理(二)》

我們這一章分為三個(gè)部分:1. Runtime動(dòng)態(tài)添加實(shí)現(xiàn)方法 2. Runtime動(dòng)態(tài)方法傳遞 3. Runtime更換方法; 核心都是 “消息動(dòng)態(tài)解析”。這一篇也叫淘氣篇

第一部分:“動(dòng)態(tài)添加實(shí)現(xiàn)方法”: 只寫實(shí)例方法,但是不提供方法的實(shí)現(xiàn)。驗(yàn)證當(dāng)找不到方法的實(shí)現(xiàn)時(shí),動(dòng)態(tài)添加方法

  • 創(chuàng)建Boby類

// Boby.h
@interface Boby : NSObject
@property (nonatomic, copy) NSString *name;
- (void)eating;
@end
  • ---- > // Boby.m
#import "Boby.h"
#if TARGET_IPHONE_SIMULATOR
#import <objc/runtime.h>
#else
#import <objc/runtime.h>
#import <objc/message.h>
#endif
@implementation Boby
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    // 動(dòng)態(tài)添加方法
    if ([NSStringFromSelector(sel) isEqualToString:@"eating"]) {
        class_addMethod(self, sel, (IMP)eateat, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}
void eateat(id self, SEL cmd)
{
    NSLog(@"%@ 吃貨就知道吃。。。。!。 倒架子。。。",((Boby *)self).name);
}

*----

int main(int argc, const char * argv[]) {
Boby *minBoby = [[Boby alloc] init];
minBoby.name = @"哈利波特";
[minBoby eating];
return 0;
}


看我們打印的結(jié)果吧:
`
2016-04-11 21:16:56.967 RuntimeLine[2348:195944] 哈利波特 吃貨就知道吃。。。。!。 倒架子。。。
`

> 呵呵, 。好像冤枉了,.h只是提供了個(gè)API,.m并沒有實(shí)現(xiàn)這個(gè)API,意思就是人家想干,卻是沒干,結(jié)果就是干了, 反正成果擺在哪兒,這是偷干,額,不對(duì),暗度陳倉(cāng) 類里面調(diào)用函數(shù),真是騙到了,哎
人家.m沒干,沒有`eating`的方法實(shí)現(xiàn),因此在調(diào)用此方法的時(shí)候,會(huì)調(diào)用`resolveInstanceMethod`方法,卻是動(dòng)態(tài)添加了方法。他還可以返回No,繼續(xù)向下傳遞。接下來(lái)。。。

###第二部分:“動(dòng)態(tài)方法傳遞”: 本來(lái)朕沒干,可以偷干的,卻給波特干了

下面剛才的代碼,添加一個(gè)Cat
* > 創(chuàng)建Cat類

// Cat.h

import <Foundation/Foundation.h>

@interface Cat : NSObject
@property (copy, nonatomic) NSString * name;
@end.h
@interface Boby : NSObject
@property (nonatomic, copy) NSString *name;

  • (void)eating;
    @end

* ---- > // Cat.h.m

import "Cat.h"

import "Boby.h"

@implementation Cat
// 1. 我是拒絕的 不動(dòng)態(tài)添加方法, 返回NO 進(jìn)入2

  • (BOOL)resolveInstanceMethod:(SEL)sel
    {
    return NO;
    }
    // 2. 我再次拒絕,不指定備選對(duì)象響應(yīng)aselector,進(jìn)入3
  • (id)forwardingTargetForSelector:(SEL)aSelector
    {
    return nil;
    }
    // 3. 我還是拒絕,給他返回方法選擇器, 進(jìn)入4
  • (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
    {
    if ([NSStringFromSelector(aSelector) isEqualToString:@"eating"]) {
    return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return [super methodSignatureForSelector:aSelector];
    }
    // 4. 算了,答應(yīng)了,但是不能這么爽快,不然,修改調(diào)用對(duì)象
  • (void)forwardInvocation:(NSInvocation *)anInvocation
    {
    Boby *boby = [[Boby alloc] init];
    boby.name = @"波特哥哥";
    [anInvocation invokeWithTarget:boby];
    }

*----

* 

> ````
//記住應(yīng)該這樣的
int main(int argc, const char * argv[]) {
    Cat * cat = [[Cat alloc] init];
    cat.name = @"我是朕,鏟屎官。。。"; //記住應(yīng)該這樣的
    ((void(*)(id, SEL))objc_msgSend)((id)cat, @selector(eating));
    return 0;
}
//記住應(yīng)該這樣的

結(jié)果打印是這樣的:
2016-04-11 21:56:07.323 RuntimeLine[2483:214357] 波特哥哥 吃貨就知道吃。。。。!。 倒架子。。。

喵喵, ??拥?,. 鏟屎官,為毛沒朕的份呢???,意思就是本來(lái)朕偷干的,卻是給波特兄弟偷干了,.
其實(shí)鏟屎官使壞了,Cat(朕)在.m嬌氣,冷艷,三次拒絕之后又自己說(shuō)給波特的,結(jié)果呢?鏟屎的成功更換了對(duì)象,把對(duì)象更換為波特兄弟了,朕只會(huì)跳舞不行哦, 還要會(huì)魔法才行,看來(lái)討好鏟屎官才是王道?。?!

第三部分:“更換方法” 干了一件別的事

  • 還是用Boby類來(lái)搞

// Boby.h
@interface Boby : NSObject
@end
  • ---- > // Boby.m
#import "Boby.h"
#if TARGET_IPHONE_SIMULATOR
#import <objc/runtime.h>
#else
#import <objc/runtime.h>
#import <objc/message.h>
#endif
@implementation Boby
// 1. 我是拒絕的 不動(dòng)態(tài)添加方法, 返回NO 進(jìn)入2
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    return NO;
}
// 2. 我再次拒絕,不指定備選對(duì)象響應(yīng)aselector,進(jìn)入3
- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return nil;
}
// 3. 我還是拒絕,給他返回方法選擇器, 進(jìn)入4
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    if ([NSStringFromSelector(aSelector) isEqualToString:@"eating"]) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return [super methodSignatureForSelector:aSelector];
}
// 4. 算了,答應(yīng)了,但是不能這么爽快,不然,修改調(diào)用對(duì)象
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    [anInvocation setSelector:@selector(changeMagic)];
    [anInvocation invokeWithTarget:self];
}
// 如果forwardInvocation沒實(shí)現(xiàn),就會(huì)調(diào)用這個(gè)方法
- (void)doesNotRecognizeSelector:(SEL)aSelector
{
    NSLog(@"消息處長(zhǎng)不干了: %@", NSStringFromSelector(aSelector));
}
- (void)changeMagic 
{
    NSLog(@"變魔法。。。。");
}

*----

int main(int argc, const char * argv[]) {
Boby minBoby = [[Boby alloc] init];
((void(
)(id, SEL))objc_msgSend)((id)minBoby, @selector(eating));
return 0;
}


打印的結(jié)果:
`
2016-04-11 23:37:50.890 RuntimeLine[3180:255959] 變魔法。。。。
`
更換了方法,有吃變?yōu)榱四Х? 干了一件別的事。。。什么感覺

> ###案例小結(jié):
看看我們都干了什么?!What have we done??。?!
此實(shí)戰(zhàn)內(nèi)容是
`resolveInstanceMethod:(SEL)sel
forwardingTargetForSelector:(SEL)aSelector
methodSignatureForSelector:(SEL)aSelector
forwardInvocation:(NSInvocation *)anInvocation
doesNotRecognizeSelector:(SEL)aSelector`
這個(gè)方法使用而已,沒什么難的吧,就當(dāng)學(xué)習(xí)一下scrollview這么簡(jiǎn)單吧

回顧一下:1. 動(dòng)態(tài)添加實(shí)現(xiàn)方法 2. 動(dòng)態(tài)方法傳遞 3. 更換方法。

下一篇繼續(xù): [《Runtime梳理(四)》](http://www.itdecent.cn/p/65dd981334d6)
最后編輯于
?著作權(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)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,068評(píng)論 0 9
  • 繼上Runtime梳理(四) 通過(guò)前面的學(xué)習(xí),我們了解到Objective-C的動(dòng)態(tài)特性:Objective-C不...
    小名一峰閱讀 848評(píng)論 0 3
  • 一、概述 Objective-C語(yǔ)言是一門動(dòng)態(tài)語(yǔ)言,它將很多靜態(tài)語(yǔ)言在編譯和鏈接期所做的事推遲到運(yùn)行時(shí)處理。這種動(dòng)...
    Fly晴天里Fly閱讀 1,299評(píng)論 0 6
  • 我們常常會(huì)聽說(shuō) Objective-C 是一門動(dòng)態(tài)語(yǔ)言,那么這個(gè)「動(dòng)態(tài)」表現(xiàn)在哪呢?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,339評(píng)論 0 7
  • 對(duì)于從事 iOS 開發(fā)人員來(lái)說(shuō),所有的人都會(huì)答出【runtime 是運(yùn)行時(shí)】什么情況下用runtime?大部分人能...
    夢(mèng)夜繁星閱讀 3,812評(píng)論 7 64

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