iOS知识加固(一)-Runtime篇

我只是知识的搬运工,为了应对面试和巩固知识体系,简化和整理了有关runtime的知识点,以求能快速理解和记忆。

(一)Runtime概念

  1. Runtime是用C、C++、汇编写的一套框架
  2. Objective-C语言是以Runtime为核心对C的扩展
  3. Runtime使得Objective-C拥有面向对象和动态的特性
  4. Runtime的核心就是消息机制(Messaging)

Runtime形成的动态特性:

  1. 数据类型推迟到运行时确定
  2. 方法推迟到运行时进行选择和变更

以我个人的理解,程序是到运行时将我们所写的OC语言转换成C语言,进而转换成计算机识别的汇编语言,而由OCC转换时,Runtime库根据我们的代码联系上下文形成明确的指令。

消息机制秉承万物皆对象的思想,将类、实例对象、方法等当做一个消息指令:哪个对象,执行了哪个方法,附带了哪些参数,主谓宾集齐便凑成一句完整的话传递给计算机。

1.1 消息传递

OC中类、对象以及方法本质都是结构体,这个结构体就是一个信息集合的单位,OC底层实现中涉及以下几个概念:

  • 类对象(objc_class)
  • 实例(objc_object)
  • 元类(Meta Class)
  • Method(objc_method)
  • SEL(objc_selector)
  • IMP
  • 类缓存(objc_cache)
  • Category(objc_category)

1.1.1 isa指针

所有的实例对象其实都是同样的结构体(objc_object),id也是这个结构体类型,故能指向所有对象,而这个objc_object结构体内只有一个指针isa,指向这个对象的类对象(objc_class),类对象的结构体里包含属性列表(ivars)、方法列表(methodLists)等,类对象的isa指针指向类对象的类,称之为元类(metaclass),另外类对象在编译期间产生了实例对象,是单例,所以isa表达了类和实例的逻辑关系(参见下图,详细底层代码请阅读结尾博文)

  • 对象(instance)的isa指向类(class object)
  • 类(class object)的isa指向元类(metaclass)
  • 元类(metaclass)的isa指向根元类(root metaclass)
isa指针指向

1.1.2 method

Method是方法的结构体,其中包含SELIMP和方法类型属性,个人理解SEL是方法索引,IMP是方法的具体实现。

1.1.3 类缓存(objc_cache)和Category(objc_category)

一个class 往往只有 20% 的函数会被经常调用,可能占总调用次数的 80% 。每个消息都需要遍历一次objc_method_list 并不合理。如果把经常被调用的函数缓存下来,那可以大大提高函数查询的效率。这也就是objc_class 中另一个重要成员objc_cache做的事情。
Category是表示一个指向分类的结构体的指针,其结构体内包含实例方法集合(instanceMethods)、类方法集合(classMethods)、协议集合(protocols)、属性集合(instanceProperties)、要拓展的类(cls)和类名称。

1.2 消息转发

消息传递过程中如果没有找到方法,系统给出挽回的三次机会。

1.2.1 动态方法解析

首先,Objective-C运行时会调用+(BOOL)resolveInstanceMethod:(SEL)sel或者+ (BOOL)resolveClassMethod:(SEL)sel,让你有机会提供一个函数实现。如果你添加了函数并返回YES, 那运行时系统就会重新启动一次消息发送的过程。询问是否有动态添加方法来进行处理。

1.2.2 备用接收者

如果目标对象实现了-(id)forwardingTargetForSelector:(SEL)aSelector,Runtime 这时就会调用这个方法,给你把这个消息转发给其他对象的机会。

1.2.3 完整消息转发(消息重定向)

如果在上一步还不能处理未知消息,则唯一能做的就是启用完整的消息转发机制了。
首先它会发送-methodSignatureForSelector:消息获得函数的参数和返回值类型。如果-methodSignatureForSelector:返回nilRuntime则会发出-doesNotRecognizeSelector:消息,程序这时也就挂掉了。如果返回了一个函数签名,Runtime就会创建一个NSInvocation对象并发送-forwardInvocation:消息给目标对象。

(二)API

  • objc_msgSend(对象, @selector(方法),参数)
  • objc_getClass("类名", sel):返回当前类,当你找的类不存在,返回nil;
  • objc_lookUpClass("类名", sel):返回当前类,当你找的类不存在,返回nil;
  • objc_getRequiredClass("类名", sel):返回当前类,当你要找的类不存在的话会闪退,慎用。
  • object_getClass("类名", sel):通过对象返回当前类
  • class_addMethod([Person class], sel, (IMP)eat, "v@:@"):1.类类型;2.方法编号;3.方法实现,函数指针;4.返回值类型(c语言字符串),看文档
  • Ivar *ivars = class_copyIvarList([Person class], &count)
  • const char *name = ivar_getName(ivar)
  • free(ivars)
  • method_exchangeImplementations(Method, Method)

(三)应用

  • 关联对象(Objective-C Associated Objects)给分类增加属性(objc_setAssociatedObject)
  • 方法魔法(Method Swizzling)方法添加和替换和KVO实现
  • 消息转发(热更新)解决Bug(JSPatch)
  • 实现NSCoding的自动归档和自动解档
  • 实现字典和模型的自动转换(MJExtension)

练习

  1. isa指针指向问题
    BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
    BOOL res2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
    BOOL res3 = [(id)[Person class] isKindOfClass:[NSObject class]];
    BOOL res4 = [(id)[Person class] isMemberOfClass:[NSObject class]];
    BOOL res5 = [(id)[Person class] isKindOfClass:[Person class]];
    BOOL res6 = [(id)[Person class] isMemberOfClass:[Person class]];
    NSLog(@"\n%d\n%d\n%d\n%d\n%d\n%d",res1,res2,res3,res4,res5,res6);
  1. 利用Runtime,在程序运行的过程中,动态创建一个类;
  2. 利用Runtime,在程序运行的过程中,动态创建一个类的属性/方法;
  3. 遍历一个类的所有成员变量;

声明:参考以下博文,经过自己修改加工,为记录学习使用
iOS Runtime详解
iOS Runtime《一》 类Class 相关
你真的明白isKindOfClass 和 isMemberOfClass 的区别么?
深入理解iOS开发中的isa指针
iOS消息机制相关
iOS Runtime《一》 类Class 相关
解读objc_msgSend

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

推荐阅读更多精彩内容