ios runtime入门


runtime: 运行时机制

学的有点凌乱,记一下

runtime是OC的底层,一套纯C的api,我们平时写的OC代码,都会通过runtime编译成C语言

导入#import <obj/message.h>包含#include<obj/runtime>


图1

在build setting中搜索msg把选项改为NO否者会不出现提示且报错。

OC通过消息发送进行传递的 objc_msgSend(class,SEL,arg1, arg2, ...);

class:消息的接收者,SEL:方法名,arg...参数列表

[self sel];运行方法时如果遇到没有的方法会出现报错编译不通过,通过[self performSelector:@selector(sel)];

预加载

+(void)load;

在程序一开始就执行,在main方法之前,想更改全局的一些方法可以放在这里

比如你想重写系统的方法可愿意在这

先写一个url的分类

然后写一个和系统方法类似的方法

+(instancetype)J_URLWithString:(NSString *)URLString{

    NSURL *url = [NSURL URLWithString:URLString];

    if (url == nil) {

        NSLog(@"nil");

    }

    return url;

}

然后就是重写load方法

+(void)load{

    //交换放方法的调用顺序

    Method urlWithStr = class_getClassMethod(self, @selector(URLWithString:));

    Method urlWithJStr = class_getClassMethod(self, @selector(J_URLWithString:));

    method_exchangeImplementations(urlWithStr, urlWithJStr);

}

这样就可以通过交货IMP来实现两个方法的调用了,运行一下


你会发现递归了应为要把自己写的方法中系统方法改为自己写的方法

+(instancetype)JSC_URLWithString:(NSString *)URLString{

    NSURL *url = [NSURL JSC_URLWithString:URLString];

    if (url == nil) {

        NSLog(@"nil");

    }

    return url;

}

Cache

Cache 为方法调用的性能进行优化,每当实例对象接收到一个消息时,它不会直接在 isa 指针指向的类的方法列表中遍历查找能够响应的方法,因为每次都要查找效率太低了,而是优先在 Cache 中查找。

Runtime 系统会把被调用的方法存到 Cache 中,如果一个方法被调用,那么它有可能今后还会被调用,下次查找的时候就会效率更高。就像计算机组成原理中 CPU 绕过主存先访问 Cache 一样。

IMP

它就是一个函数指针,方法编号,指向方法。

ISA

objc_object 结构体包含一个 isa 指针,根据 isa 指针就可以找到对象所属的类。

通过kvo可以看到

建一个Person类

[p addObserver:self forKeyPath:@"name" options:(NSKeyValueObservingOptionNew) context:nil];来监听他的name属性,打个断点这句话运行完,发现p的isa指向的Person变成了系统通过runtime创建的子类NSKVONOtyfing_Person;

我们创建一个NSObject的分类

-(void)J_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context{

    //

    NSString *oldName = NSStringFromClass(self.class);

    NSString *newName = [@"JKVO_" stringByAppendingString:oldName];

    Class newClass = objc_allocateClassPair(self.class/*继承自*/, newName.UTF8String/*类名*/, 0);

    objc_registerClassPair(newClass);//注册该类

    object_setClass(self, newClass);把该类指向NewClass

    //动态添加方法

    class_addMethod(newClass, @selector(setName:), (IMP)setName, "v@:@");

}

void setName(id self,SEL _cmd,NSString *newName){

NSLog(@"拿到了%@",newName);

}

Method

Method 代表类中某个方法的类型

方法中的隐藏参数

id self,SEL _cmd;

接受消息的对象(self 所指向的内容,当前方法的对象指针)

方法选择器(_cmd 指向的内容,当前方法的 SEL 指针)

resolveInstanceMethod: 和 resolveClassMethod: 

方法添加实例方法实现和类方法实现。runtime在类中找不到方法时会执行的方法

重定向


消息转发机制执行前,Runtime 系统允许我们替换消息的接收者为其他对象。

-(id)forwardingTargetForSelector:(SEL)aSelector{

    NSLog(@"sel = %@",NSStringFromSelector(aSelector));

    return [super forwardingTargetForSelector:aSelector];

}

如果此方法返回 nil 或者 self,则会计入消息转发机制(forwardInvocation:),否则将向返回的对象重新发送消息。

转发


当动态方法解析不做处理返回 NO 时,则会触发消息转发机制。这时 forwardInvocation: 方法会被执行,我们可以重写这个方法来自定义我们的转发逻辑:

-(void)forwardInvocation:(NSInvocation *)anInvocation{

    NSLog(@"---%@",anInvocation);

    //拿SEL方法

    SEL sel = [anInvocation selector];

    //转发

    Animation *anim = [Animation new];

    if ([anim respondsToSelector:sel]) {

        //调用这个对象

        [anInvocation invokeWithTarget:anim];

    }else{

        [super forwardInvocation:anInvocation];

    }

}

在 forwardInvocation: 消息发送前,Runtime 系统会向对象发送methodSignatureForSelector: 消息,并取到返回的方法签名用于生成 NSInvocation 对象。所以重写 forwardInvocation: 的同时也要重写 methodSignatureForSelector: 方法,否则会抛异常。

-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{

    NSString *sel = NSStringFromSelector(aSelector);

    if ([sel isEqualToString:@"run"]) {

        return [NSMethodSignature signatureWithObjCTypes:"v@:"];

    }

    return [super methodSignatureForSelector:aSelector];

}

当一个对象没有相应的方法实现而无法响应某消息的时候触发

-(void)doesNotRecognizeSelector:(SEL)aSelector{

    NSString *sel = NSStringFromSelector(aSelector);

    NSLog(@"---%@  不存在",sel);

}


可以通过转发实现多继承

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

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,694评论 0 9
  • 我们常常会听说 Objective-C 是一门动态语言,那么这个「动态」表现在哪呢?我想最主要的表现就是 Obje...
    Ethan_Struggle阅读 2,188评论 0 7
  • 参考链接: http://www.cnblogs.com/ioshe/p/5489086.html 简介 Runt...
    乐乐的简书阅读 2,132评论 0 9
  • 本文转载自:http://yulingtianxia.com/blog/2014/11/05/objective-...
    ant_flex阅读 755评论 0 1
  • 继上Runtime梳理(四) 通过前面的学习,我们了解到Objective-C的动态特性:Objective-C不...
    小名一峰阅读 744评论 0 3