13- Runtime 学习参考:从实际应用出发(从使用到概念)

前话

这段时间学习 Runtime,网上看了一些文章,这里整理一下,给准备学 Runtime 的朋友一个参考.希望大家可以看完'前话'-----'Demo 下载'小节,再去看提到的文章.

Runtime 中最重要的就是消息机制.

参考

如这里边很多文章的作者提到的那样, Runtime 文章网上很多,但不是每一篇我们新手都能看懂,有一些直接堆积概念,作为初学的我们,肯定满头雾水. 学习一个陌生的东西,我觉得我们学习的路径,最好是先对其的概念有个很简单浅显的理解,然后仿照写几个 Demo,消除陌生感后,我们再深入的了解一下实现机制和具体方法的含义.

我第一篇看的文章 《OC最实用的runtime总结,面试、工作你看我就足够了!》,这篇文章很浅显,很易懂.跟着写完里边所有提到的案例之后,发现 Runtime 并没有半年前在网上打算学习看的那篇冗余的文章的所伴随的满头雾水.基本上对 Runtime 的基本方法有了一个具体的了解.

从这里,我们总结出 Runtime 的一些基本的函数方法,如下

  • 获得某个类的类方法 Method class_getClassMethod(Class cls , SEL name)

  • 获得某个类的实例对象方法 Method class_getInstanceMethod(Class cls , SEL name)

  • 交换两个方法的实现 void method_exchangeImplementations(Method m1 , Method m2)

  • set方法,将值value 跟对象object 关联起来(将值value 存储到对象object 中) 参数 object:给哪个对象设置属性 参数 key:一个属性对应一个Key,将来可以通过key取出这个存储的值,key 可以是任何类型:double、int 等,建议用char 可以节省字节 参数 value:给属性设置的值 参数policy:存储策略 (assign 、copy 、 retain就是strong) void objc_setAssociatedObject(id object , const void *key ,id value ,objc_AssociationPolicy policy)

  • 利用参数key 将对象object中存储的对应值取出来 id objc_getAssociatedObject(id object , const void *key) 获得某个类的所有成员变量(outCount 会返回成员变量的总数) 参数: 1、哪个类 2、放一个接收值的地址,用来存放属性的个数 3、返回值:存放所有获取到的属性,通过下面两个方法可以调出名字和类型 Ivar *class_copyIvarList(Class cls , unsigned int *outCount)

  • 获得成员变量的名字 const char *ivar_getName(Ivar v)

  • 获得成员变量的类型 const char *ivar_getTypeEndcoding(Ivar v)

  • 获取协议列表 protocol_getName

  • 获取属性列表 property_getName

文/滕先洪(简书作者) 原文链接:http://www.jianshu.com/p/ab966e8a82e2 著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

然后,在 Swift 第一届参会群里,看到正好有人讨论 Runtime,有人截图在百度搜索靠前的这篇文章 《Runtime 10种用法(没有比这更全的了)》,名字有点夸张,但是相信作者把文章中提到的几个篇文章都已经看了一遍.如果我们把这些文章看一遍的话,基本对 Runtime 能够有个大概的了解了.而且这篇文章中,作者对几篇文章做了一个简单的概括.

从这里我们得出, Runtime的简单实用场景:

  • 动态交换两个方法的实现(Swizzle 黑魔法)
  • 拦截交换系统自带的方法(Swizzle 黑魔法)
  • 动态给分类的成员变量和成员方法
  • 给分类增加属性
  • 获得一个类的所有成员变量
  • 获取一个类的类方法,对象方法
  • 字典转模型,MJExtesion和 YYModel的基本实现原理
  • 动态添加方法 performSelector
  • 实现NSCoding的自动归档和自动解档
  • 在方法上增加额外功能
  • 动态更改变量的值

《Runtime 10种用法(没有比这更全的了)》这篇文章里提到了上边《OC最实用的runtime总结,面试、工作你看我就足够了!》这篇文章,除了这篇文章,还有《让你快速上手Runtime》,小码哥袁铮写的.

《runtime详解》这篇文章除了我们上边提到的几个基本用法之外,我们主要在这篇文章中查看几个参数的概念:

  • objc_msgSend
  • SEL
  • id
  • Class
  • Method
  • IMP
  • Cache
  • Property

《详解runtime运行时机制 》其中也有对参数的解析(和上一篇有重复),另外这篇文章,适合我们在基本掌握了前边 Runtime 的使用方法之后,想要对很多概念更加深入了解的诉求.比如:Method和IMP

除了上述几篇文章,在方法替换的时候,为了比较方法替换两种写法的区别,我还阅读了《Objective-C的方法替换》这篇文章

Runtime消息机制

如同最开始上边说的那样,Runtime最重要的就是消息机制,了解消息机制,查看苹果开源的实现源码,会让我们更加了解苹果针对Object-C语言的用心和强大。这篇文章《runtime-消息机制》推荐给大家,期间有些地方我也没有看懂,作者自己也说了,为了写这篇文章,看苹果源码头都大了。我们又不是天才,怎么可能随随便便就懂得。好在有人给我们整理了这些,我们站在巨人的肩膀上,再看源码即使有不清楚的地方,也有参考和指导。
还有该作者的另一篇文章《runtime-属性与变量》,写的很用心。

实战

在实际项目过程中,我遇到下边情况,我们都可以用Runtime完成:

  • 实现万能控制器跳转《iOS 万能跳转界面方法 (runtime实用篇一))》
  • 还有就是检测用户上网时候准确使用了多少数据流量.这对于现在 QQ, 网易云音乐赠送用户数据流量的统计十分重要
  • 适配iOS时,我们有时候不同系统版本的手机的iOS所用到的图片素材不一样,也可以用运行时轻松完成.这个实例在提到的文章中还有我的Demo代码下载中都有写出.

其它

在阅读 Runtime文章的时候,我还对元类和超类的概念比较的模糊.超类其实就是我们在翻译的时候,对 super class 的另一种翻译法,我们一般叫他'父类',这样也更加容易理解. 元类可以读《Objective-C 中的元类(meta class)是什么?》这篇文章.我们首先搞清楚对象和类的数据结构,更加有助于理解. 加单来说元类就是类的类,而元类的类叫做根元类.以此类推,所有的元类使用根元类作为他们的类,根元类的元类则就是它自己。也就是说基类的元类的isa指针指向他自己。

Demo 下载

我已经对上边的 Runtime 的大部分代码进行了梳理,需要的可以点过来Demo 链接

文章段落摘要

(如有侵权,请联系我,立刻删除)

1.. 还有一些 NSObject 的方法可以从 Runtime 系统中获取信息,允许对象进行自我检查。例如: - class方法返回对象的类; - isKindOfClass: 和 -isMemberOfClass: 方法检查对象是否存在于指定的类的继承体系中(是否是其子类或者父类或者当前类的成员变量); - respondsToSelector: 检查对象能否响应指定的消息; - conformsToProtocol:检查对象是否实现了指定协议类的方法; - methodForSelector: 返回指定方法实现的地址。 文/Ammar(简书作者)

原文链接:http://www.jianshu.com/p/1e06bfee99d0

著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

2.. 值得注意的时,objc_class 中也有一个 isa 指针,这说明 Objc 类本身也是一个对象。为了处理类和对象的关系,Runtime 库创建了一种叫做 Meta Class(元类) 的东西,类对象所属的类就叫做元类。Meta Class 表述了类对象本身所具备的元数据。 我们所熟悉的类方法,就源自于 Meta Class。我们可以理解为类方法就是类对象的实例方法。每个类仅有一个类对象,而每个类对象仅有一个与之相关的元类。 当你发出一个类似 NSObject alloc 的消息时,实际上,这个消息被发送给了一个类对象(Class Object),这个类对象必须是一个元类的实例,而这个元类同时也是一个根元类(Root Meta Class)的实例。所有元类的 isa 指针最终都指向根元类。 所以当 [NSObject alloc] 这条消息发送给类对象的时候,运行时代码 objc_msgSend() 会去它元类中查找能够响应消息的方法实现,如果找到了,就会对这个类对象执行方法调用。

图
上图实现是 super_class 指针,虚线时 isa 指针。而根元类的父类是 NSObject ,isa 指向了自己。而 NSObject 没有父类。 最后 objc_class 中还有一个 objc_cache ,缓存,它的作用很重要,后面会提到。

文/Ammar(简书作者) 原文链接:http://www.jianshu.com/p/1e06bfee99d0

著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

3.. 获取方法地址 NSObject 类中有一个实例方法:methodForSelector , 你可以用它来获取某个方法选择器对应的 IMP ,举个例子: void (setter)(id, SEL, BOOL); int i; setter = (void ()(id, SEL, BOOL))[target methodForSelector:@selector(setFilled:)]; for ( i = 0 ; i < 1000 ; i++ ) setter(targetList[i], @selector(setFilled:), YES);

当方法被当做函数调用时,两个隐藏参数也必须明确给出,上面的例子调用了1000次函数,你也可以尝试给 target 发送1000次 setFilled: 消息会花多久。 虽然可以更高效的调用方法,但是这种做法很少用,除非时需要持续大量重复调用某个方法的情况,才会选择使用以免消息发送泛滥。 注意: methodForSelector: 方法是由 Runtime 系统提供的,而不是 Objc 自身的特性

文/Ammar(简书作者) 原文链接:http://www.jianshu.com/p/1e06bfee99d0

著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

4.. 动态绑定所做的,即是在实例所属类确定后,将某些属性和相应的方法绑定到实例上。这里所指的属性和方法当然包括了原来没有在类中实现的,而是在运行时才需要的新加入的实现。**在Cocoa层,我们一般向一个NSObject对象发送-respondsToSelector:或者-instancesRespondToSelector:等来确定对象是否可以对某个SEL做出响应,而在OC消息转发机制被触发之前,对应的类的+resolveClassMethod:和+resolveInstanceMethod:将会被调用,
**在此时有机会动态地向类或者实例添加新的方法,也即类的实现是可以动态绑定的。

文/Onevcat(简书作者) 原文链接:https://onevcat.com/2012/04/objective-c-runtime/

著作权归作者所有,转载请联系作者获得授权,并标注“作者”。

参考文章

  1. 《OC最实用的runtime总结,面试、工作你看我就足够了!》
  2. 《Objective-C的方法替换》
  3. 《Runtime 10种用法(没有比这更全的了)》
  4. 《IOS SEL (@selector) 原理及使用总结(一)》
  5. 《iOS 万能跳转界面方法 (runtime实用篇一))》
  6. 《详解runtime运行时机制 》
  7. 《runtime详解》
  8. 《Runtime 10种用法(没有比这更全的了)》
  9. 《让你快速上手Runtime》
  10. 《官方维护的 Demo》
  11. 《猫神提到的 Runtime》
  12. 《runtime-消息机制》
  13. 《runtime-属性与变量》

交流

希望能和大家交流技术

我的博客地址: http://www.lilongcnc.cc/


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

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,703评论 0 9
  • 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的...
    西木阅读 30,551评论 33 466
  • 转载:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麦子阅读 730评论 0 2
  • 对于从事 iOS 开发人员来说,所有的人都会答出【runtime 是运行时】什么情况下用runtime?大部分人能...
    梦夜繁星阅读 3,715评论 7 64
  • 本文内容来自hackersome 专题目录如下: GitHub上Star最多的100个python reposit...
    Gevin阅读 3,275评论 0 12