Runtime梳理(三)

挖就挖底层.png

继上《Runtime梳理(二)》

我们这一章分为三个部分:1. Runtime动态添加实现方法 2. Runtime动态方法传递 3. Runtime更换方法; 核心都是 “消息动态解析”。这一篇也叫淘气篇

第一部分:“动态添加实现方法”: 只写实例方法,但是不提供方法的实现。验证当找不到方法的实现时,动态添加方法

  • 创建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
{
    // 动态添加方法
    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;
}


看我们打印的结果吧:
`
2016-04-11 21:16:56.967 RuntimeLine[2348:195944] 哈利波特 吃货就知道吃。。。。!。 倒架子。。。
`

> 呵呵, 。好像冤枉了,.h只是提供了个API,.m并没有实现这个API,意思就是人家想干,却是没干,结果就是干了, 反正成果摆在哪儿,这是偷干,额,不对,暗度陈仓 类里面调用函数,真是骗到了,哎
人家.m没干,没有`eating`的方法实现,因此在调用此方法的时候,会调用`resolveInstanceMethod`方法,却是动态添加了方法。他还可以返回No,继续向下传递。接下来。。。

###第二部分:“动态方法传递”: 本来朕没干,可以偷干的,却给波特干了

下面刚才的代码,添加一个Cat
* > 创建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. 我是拒绝的 不动态添加方法, 返回NO 进入2

  • (BOOL)resolveInstanceMethod:(SEL)sel
    {
    return NO;
    }
    // 2. 我再次拒绝,不指定备选对象响应aselector,进入3
  • (id)forwardingTargetForSelector:(SEL)aSelector
    {
    return nil;
    }
    // 3. 我还是拒绝,给他返回方法选择器, 进入4
  • (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
    {
    if ([NSStringFromSelector(aSelector) isEqualToString:@"eating"]) {
    return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return [super methodSignatureForSelector:aSelector];
    }
    // 4. 算了,答应了,但是不能这么爽快,不然,修改调用对象
  • (void)forwardInvocation:(NSInvocation *)anInvocation
    {
    Boby *boby = [[Boby alloc] init];
    boby.name = @"波特哥哥";
    [anInvocation invokeWithTarget:boby];
    }

*----

* 

> ````
//记住应该这样的
int main(int argc, const char * argv[]) {
    Cat * cat = [[Cat alloc] init];
    cat.name = @"我是朕,铲屎官。。。"; //记住应该这样的
    ((void(*)(id, SEL))objc_msgSend)((id)cat, @selector(eating));
    return 0;
}
//记住应该这样的

结果打印是这样的:
2016-04-11 21:56:07.323 RuntimeLine[2483:214357] 波特哥哥 吃货就知道吃。。。。!。 倒架子。。。

喵喵, 。坑爹呀,. 铲屎官,为毛没朕的份呢???,意思就是本来朕偷干的,却是给波特兄弟偷干了,.
其实铲屎官使坏了,Cat(朕)在.m娇气,冷艳,三次拒绝之后又自己说给波特的,结果呢?铲屎的成功更换了对象,把对象更换为波特兄弟了,朕只会跳舞不行哦, 还要会魔法才行,看来讨好铲屎官才是王道!!!

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

  • 还是用Boby类来搞

// 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. 我是拒绝的 不动态添加方法, 返回NO 进入2
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    return NO;
}
// 2. 我再次拒绝,不指定备选对象响应aselector,进入3
- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return nil;
}
// 3. 我还是拒绝,给他返回方法选择器, 进入4
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    if ([NSStringFromSelector(aSelector) isEqualToString:@"eating"]) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return [super methodSignatureForSelector:aSelector];
}
// 4. 算了,答应了,但是不能这么爽快,不然,修改调用对象
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    [anInvocation setSelector:@selector(changeMagic)];
    [anInvocation invokeWithTarget:self];
}
// 如果forwardInvocation没实现,就会调用这个方法
- (void)doesNotRecognizeSelector:(SEL)aSelector
{
    NSLog(@"消息处长不干了: %@", 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;
}


打印的结果:
`
2016-04-11 23:37:50.890 RuntimeLine[3180:255959] 变魔法。。。。
`
更换了方法,有吃变为了魔法了, 干了一件别的事。。。什么感觉

> ###案例小结:
看看我们都干了什么?!What have we done?!!!
此实战内容是
`resolveInstanceMethod:(SEL)sel
forwardingTargetForSelector:(SEL)aSelector
methodSignatureForSelector:(SEL)aSelector
forwardInvocation:(NSInvocation *)anInvocation
doesNotRecognizeSelector:(SEL)aSelector`
这个方法使用而已,没什么难的吧,就当学习一下scrollview这么简单吧

回顾一下:1. 动态添加实现方法 2. 动态方法传递 3. 更换方法。

下一篇继续: [《Runtime梳理(四)》](http://www.jianshu.com/p/65dd981334d6)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,636评论 0 9
  • 继上Runtime梳理(四) 通过前面的学习,我们了解到Objective-C的动态特性:Objective-C不...
    小名一峰阅读 719评论 0 3
  • 一、概述 Objective-C语言是一门动态语言,它将很多静态语言在编译和链接期所做的事推迟到运行时处理。这种动...
    Fly晴天里Fly阅读 1,181评论 0 6
  • 我们常常会听说 Objective-C 是一门动态语言,那么这个「动态」表现在哪呢?我想最主要的表现就是 Obje...
    Ethan_Struggle阅读 2,109评论 0 7
  • 对于从事 iOS 开发人员来说,所有的人都会答出【runtime 是运行时】什么情况下用runtime?大部分人能...
    梦夜繁星阅读 3,674评论 7 64