Runtime

一、基本概念

RunTime简称运行时,就是系统在运行的时候的一些机制,其中最重要的是消息机制

C及其他语言,函数的调用在编译的时候决定调用哪个函数,完成编译后直接顺序执行,无任何二义性;OC的函数调用成为消息发送,在编译的时候并不能决定调用哪个函数,只有在真正运行的时候才会根据函数名称找到对应的函数来调用。

二、面试题一

1.runtime 怎么添加属性,方法等

【1】ivar  -- 表示成员变量

Ivar ivar = class_getInstanceVariable([XXClass class],"privateName")

【2】class_addIvar -- 添加一个成员变量

NSUInteger size;

NSUInteger alignment;

NSGetSizeAlignment("*",&size,&alignment)

class_addIvar(kclass,"expression",size,alignment,"*")

【3】class_addMethod -- 添加成员方法

class_addMethod(kclass,@selector(setExpressionFormula:),(IMP)setExpressionFormula,"v@:@")

static void setExpressionFormula(id self,SEL cmd,id value)

【4】class_addProperty -- 添加属性

class_addProperty([XXClass class],"name",attrs,3)

【5】class_addProtocol -- 添加协议

【6】class_replaceProperty -- 替换类的属性

2. runtime 如何实现 weak 属性

【1】weak属性的特点        weak策略表明该属性定义了一种“非拥有关系”。

【2】runtime如何实现weak变量的自动值nil        runtime对注册的类,会进行布局,会将weak对象放入一个hash表中。用weak指向的对象内存地址作为key,当此对象的引用计数为0的时候会调用对象的dealloc方法,假设weak指向的对象内存地址a,那么就会以a为key,在这个weak hash表中搜索,找到所有以a为key的weak对象,从而设置为nil

【3】weak属性需要在dealloc中置nil么        在ARC环境无论是强指针还是弱指针都无需再dealloc设置为nil,ARC会自动帮我们处理。即使是编译器不帮我们做这些,weak也不需要在dealloc中置nil,在属性所指的对象遭到摧毁时,属性值也会清空 

3. runtime如何通过selector找到对应的IMP地址?

每一个类对象中都有一个对象方法列表

类方法列表是存放类对象中isa指针指向的原类对象中(类方法缓存)

方法列表中每个方法结构体中记录着方法的名称,方法实现,以及参数类型,其实selector本质就是方法名称,通过这个方法名称就可以在方法列表中找到对应的方法实现。

当我们发送一个消息给一个NSObject对象时,这条消息会在对象的类对象方法列表里查找

当我们发送一个消息一个类时,这条消息会在类的MetaClass对象的方法列表里查找

4.使用runtime Associate 方法关联的对象,需要在主对象dealloc的时候释放么

无论在MRC下还是ARC下均不需要,被关联的对象在生命周期内要比对象本身释放的晚很多,它们会在被NSObject -dealloc 调用的object_disponse()方法中释放。

对象的内存销毁事件表,分四个步骤:

【1】调用 -release:引用计数变为零        对象正在被销毁,生命周期即将结束;不能再有新的 __weak 弱引用,否则将指向 nil;调用[self dealloc]

【2】父类调用 -dealloc                                继承关系中最直接继承的父类再调用 -dealloc;如果是 MRC 代码,则会手动释放实例变量们(iVars);继承关系中每一层的父类都再调用 -dealloc

【3】NSObject 调  -dealloc                        只做一件事:调用Objective-C    runtime  中object_disponse()方法

【4】调用object_disponse()                        为C++的实例变量们(iVars)调用 destructors;为 ARC 状态下的实例变量们(iVars)调用 -release;解除所有使用 runtime Associate 方法关联的对象;解除所有 __weak 引用;调用 free()    

5._objc_msgForward函数是做什么的?直接调用它将会发生什么

_objc_msgForward是IMP类型,用于消息转发的:当向一个对象发送一条消息,但它并没有实现的时候,_objc_msgForward会尝试做消息转发,直接调用_objc_msgForward是非常危险的事,这是把双刃刀,如果用不好会直接导致程序Crash。

6.能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?

不能向编译后得到的类中增加实例

分析:因为编译后的类已经注册在runtime中,类结构体重的objc_ivar_list实例变量的链表和instance_size实例变量的内存大小已经确定,同时runtime会调用class_setIvarLayout或class_setWeakIvarLayout来处理strong weak引用,所以不能向存在的类中添加实例变量

能向运行时创建的类中添加实例变量

分析:运行时创建的类是可以添加实例变量,调用 class_addIvar 函数,但是得在调用 objc_allocateClassPair 之后,objc_registerClassPair之前,原因同上。

7. 简述下Object-C中调用方法的过程(runtime)

Objective-C是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver,selector),整个过程介绍如下:

objc在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实际属性的类;然后在该类中的方法列表以及其父类方法列表中寻找方法运行;如果,在最顶层的父类(一般也就NSObject)中依然找不到相应的方法时,程序在运行时会挂掉并抛出异常unrecognized selector sent to xxx;但是在这之前,objc的运行时会给出三次拯救程序崩溃的机会。

补充说明:Runtime 铸就了Objective-C是动态语言的特性

8.什么是method swizzling(俗称黑魔法)

简单说就是进行方法交换

【1】在Objective-C中调用一个方法,其实是向一个对象发送消息,查找消息的唯一依据是selector的名字

【2】每个类都有一个方法列表,存放着方法的名字和方法实现的映射关系,selector的本质其实就是方法名,IMP有点类似函数指针,执行具体的Method实现,通过selector就可以找到对象的IMP

【3】交换方法的几种实现方式

        -1.利用 method_exchangeimplementations 交换两个方法的实现

        -2.利用 class_replaceMethod 替换方法的实现

        -3.利用 method_setImplementation 来直接设置某个方法的IMP

三、项目运用

3.1消息机制

-1.方法调用底层实现

NSObject *objc = objc_msgSend([NSObject class],@selector(alloc)); 

objc = objc_msgSend(objc,@selector(init));

-2.不要随便使用,不得已才使用

作用:调用已知私有方法,如调用没有在.h文件声明但是在.m文件实现了的方法    用runtime调用私有方法:方法编号后面开始,异常就是传入给方法的参数

objc_msgSend(p,@selector(run: str:),20,@"haha")    objc_msgSend(p,@selector(eat))

-3.对象如何找到对应的方法去调用

    1.方法保存到什么地方?    对象方法保存到类中,类方法保存到元类,每一个类都有方法列表methodList

    2.明确去哪个类中调用?    通过isa指针。(1)根据对象的isa去对应的类查找方法,isa:判断去哪个类查找对应的方法,指向方法调用的类。 (2)根据传入的方法编号SEL,里面有个哈希列表,在列表中找到对应方法Method(方法名) (3)根据方法名(函数入口)找到函数实现,函数实现在方法区

3.2 交换方法

需求:已有项目中使用的是 UIImage去加载图片,现在调用imageNamed,就需要给一个提示。

方法:1.提供分类    2.写一个加提示的方法    3.用系统方法与这个功能方法交互实现,在+load方法中实现

代码实现方式: method_exchangeImplementations   如:https://www.jianshu.com/p/75849d7ea832

3.3 动态添加方法

为什么动态添加方法?       OC是懒加载,有些方法可能很久不会调用

应用场景?                        电商,视频,社交,收费项目:会员机制中,只要会员才拥有这些功能

class_addMethod(self,sel,(IMP)run,@"v@:")

3.4 动态添加属性

需求:给NSObject添加一个name属性,动态添加属性    ->    runtime

set方法: objc_setAssociateObject(self,"name",name,OBJC_ASSOCIATION_RETAIN_NONATOMIC)

get方法: objc_getAssociatedObject(self,"name")

3.5 自动生成属性代码

需求:从网络数据中解析出字典数组,将数组转为模型时,有太多的key,可以使用下面的方法

代码:https://www.jianshu.com/p/75849d7ea832

二、面试题二

1.OC的消息机制

OC中的方法调用其实都是转成objc_msgSend函数的调用,给receiver(方法调用者)发送一条消息(selector方法名)

objc_msgSend底层有3大阶段

消息发送(当前类、父类中查找)、动态方法解析、消息转发

2.什么是Runtime?平时项目中用过么?

OC是一门动态性比较强的编程语言,允许很多操作推迟到程序运行时再进行

OC是动态性就是由Runtime来支撑和实现的,Runtime是一套C语言的API,封装了很多动态性相关函数

平时编写的OC代码,底层都是转换成了Runtime API进行调用

3.runtime具体应用

利用关联对象给分类添加属性

遍历类的所有成员变量

交换方法实现

利用消息转发机制解决方法找不到的异常问题

4.说说什么是runtime

OC是一个动态语言,OC的一切都是基本Runtime实现的平时编写的OC代码,在程序运行过程中,其实最终都是转成了runtime的C语言代码,runtime算是OC的幕后工作者

runtime是一套比较底层的纯C语言API,属于1个C语言库,包含了很多底层的C语言API

runtimeAPI的实现是用C++开发的(源码中的实现文件都是mm),是一套苹果开源的框架

三、主要使用场景

https://www.jianshu.com/p/ff06b011ab84

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

推荐阅读更多精彩内容

  • @[TOC] 1. IOS面试考察(一):runtime相关问题 1.1 runtime相关问题 runtime是...
    孔雨露阅读 940评论 0 5
  • 1.objc在向一个对象发送消息时,发生了什么? objc在向一个对象发送消息时,runtime会根据对象的isa...
    bugLife丶阅读 136评论 0 0
  • Runtime消息传递: 一个对象的方法像这样[obj foo],编译器转成消息发送objc_msgSend(ob...
    飞哥漂流记阅读 221评论 0 0
  • 1.一个objc对象的isa的指针指向什么?有什么作用? 指向他的类对象,从而可以找到对象上的方法 详解:下图很好...
    長茳阅读 376评论 0 8
  • 作者:洋仔链接:https://juejin.cn/post/6961653605652758564[https:...
    iOS的火影乱斗阅读 438评论 0 2