iOS Runtime!!!

一,什么是Runtime?

runtime就是运行时,OC是运行时语言,指不是编译的时候决定调用谁,而是运行到那的时候才决定

二,Runtime消息传递

一个对象的方法 [obj test],编译器转成消息发送objc_msgSend(obj, test)

Runtime时执行的流程是这样的:

①.首先,通过obj的isa指针找到它的class;
②.在class的method list找test;
③.如果class中没到test,继续往它的superclass中找 ;
④.一旦找到test这个函数,就去执行它的实现IMP

解释:根据isa找到本类,在本类列表里找,没有就在父类中找,一旦找到,就去执行它的实现IMP(期间有个缓存过程,下次也会先从缓存中找,没有再去缓存,使得找到更加迅速),找不到就进入消息转发相关流程(其实这样的话,封装就有意义了,多次调用同一方法肯定比多个不同方法要快)

这里解释一下isa,imp指针:
isa:

是类指针,之所以说isa是指针是因为Class其实是一个指向objc_class结构体的指针,而isa 是它唯一的私有成员变量,即所有对象都有isa指针(isa位置在成员变量第一个位置)

说一下对 isa 指针的理解, 对象的isa 指针指向哪里?isa 指针有哪两种类型?

isa 等价于 is kind of

实例对象(instance) isa 指向类对象
类对象指 isa 向元类对象
元类对象的 isa 指向元类的基类
isa 有两种类型:纯指针,指向内存地址

Root class(class)其实就是NSObject,NSObject是没有超类的,所以Root class(class)的Superclass指向nil;
每个Class都有一个isa指针指向唯一的meta class;
Root class(meta)的Superclass指向Root class(class),也就是NSObject,形成一个回路;
每个meta class的isa指针都指向Root class(meta)。(结合图)

IMP :(Implementation缩写)

(1)它是指向一个方法具体实现的指针,每一个方法都有一个对应的IMP。(可以直接调用方法的IMP指针,来避免方法调用死循环的问题)
(2)当你发起一个 ObjC 消息之后,最终它会执行的那段代码,就是由IMP这个函数指针指向了这个方法实现的。

sel:

方法名称的描述,只记录方法的编号不记录具体的方法,具体的方法是 IMP

3,转发

如果上述都没找到,则进入消息转发

〇,动态方法解析

resolveInstanceMethod(实例方法),resolveClassMethod(类方法)

解释:在此处可以添加一个方法,让你有机会添加,如果不抓住,就进入快速消息转发

①,快速消息转发
forvardingTargetForSelector

解释:这里指定对象执行什么方法,如果指定对象的方法没有实现也会崩溃,如果没指定,则返回nil,到2

②,正常消息转发
methodSignatureForSelector,forwardInvocation

解释:返回方法签名,下一步,返回nil未处理到forwardInvocation( 通过anInvocation处理)
判断当前执行的方法签名是否存在,存在则交给父类处理,不存在,则手动注册一个方法签名,当返回注册的新方法签名后,马上就会开始执行forwardInvocation,forwardInvocation里面可以没操作,但必须实现forwardInvocation方法

③,崩溃:doesnotrecognaziedselector

4,应用

①,获取类的所有属性和方法(获取后改变其属性方法,比如最左侧边滑动返回改为全屏返回)
②,为类添加关联属性(extension中,比如uiviewcontroller添加一个加载动画,uiview添加手势点击及事件回调)
③,为类动态添加方法,消息转发里面该写
④,方法交换(改变加载顺序,将load和init改变顺序,使得显示更加迅速)
⑤,给按钮添加间隔点击,方法交换

5,swift使用

Swift代码中已经没有了Objective-C的运行时消息机制, 在代码编译时即确定了其实际调用的方法. 所以纯粹的Swift类和对象没有办法使用runtime, 更不存在method swizzling.

为了兼容Objective-C, 凡是继承NSObject的类都会保留其动态性, 依然遵循Objective-C的运行时消息机制, 因此可以通过runtime获取其属性和方法, 实现method swizzling.

对于基本框架如Foundation, UIKit等, 都可以使用runtime.

①这里, 要注意Swift的代码与Objective-C代码的语法区别:

同时, 对于一般OC代码的method swizzling, 在load方法中执行即可. 而Swift没有load, 所以要在initialize中执行.

②Swift中的@objc和dynamic关键字:

继承自NSObject的类都遵循runtime, 那么纯粹的Swift类呢?
在属性和方法之前加上@objc关键字, 则一般情况下可以在runtime中使用了. 但有一些情况下, Swift会做静态优化而无法使用runtime.
要想完全使得属性和方法被动态调用, 必须使用dynamic关键字. 而dynamic关键字会隐式地加上@objc来修饰.
获取Swift类的runtime信息的方法, 还要加上Swift模块名。

附加面试题:runtime 如何实现 weak 属性?

首先要搞清楚weak属性的特点:

weak策略表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,

设置方法既不保留新值,也不释放旧值。此特质同assign类似;然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)

那么runtime如何实现weak变量的自动置nil?

runtime对注册的类,会进行布局,会将 weak 对象放入一个 hash 表中。用 weak 指向的对象内存地址作为 key,

当此对象的引用计数为0的时候会调用对象的 dealloc 方法,假设 weak 指向的对象内存地址是a,那么就会以a为key,

在这个 weak hash表中搜索,找到所有以a为key的 weak 对象,从而设置为 nil。

weak属性需要在dealloc中置nil么?

在ARC环境无论是强指针还是弱指针都无需在 dealloc 设置为 nil , ARC 会自动帮我们处理。

即便是编译器不帮我们做这些,weak也不需要在dealloc中置nil。

在属性所指的对象遭到摧毁时,属性值也会清空

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

推荐阅读更多精彩内容

  • 本文转载自:http://yulingtianxia.com/blog/2014/11/05/objective-...
    ant_flex阅读 719评论 0 1
  • Runtime的特性主要是消息(方法)传递,如果消息(方法)在对象中找不到,就进行转发,具体怎么实现的呢。我们从下...
    奔跑吧小蚂蚁阅读 395评论 1 1
  • 完整的程序生命阶段可以大致分为编辑,编译,链接,分发,安装,加载和运行这几个阶段。 Runtime 在广义上是指程...
    取昵称真讨厌阅读 1,162评论 0 1
  • 主要参考自:1、iOS运行时(Runtime)详解+Demo2、Objective-C Runtime3、神经病院...
    PierceDark阅读 1,737评论 0 39
  • >Runtime 介绍 C 语言 作为一门静态类语言,在编译阶段就已经确定了所有变量的数据类型,同时也确定好了要调...
    黎明s阅读 493评论 0 0