iOS面试剖析

Runtime相关知识点

2019-10-08  本文已影响0人  huoshe2019
Runtime知识结构

一、数据结构

数据结构

1.1、objc_object

objc_object

我们平常用的实例对象都是id类型,对应到runtime 中的objc_object。

1.2、objc_class

objc_class

我们平常用的类,对应到runtime中的objc_class。

问题1:Class这个类是否是一个对象呢?

解释:
是对象,因为Class对应runtime中的objc_class,objc_class继承于objc_object,所以被称为"类对象"。

1.3、isa指针

1.3.1、isa指针的概念

共用体isa_t

问题2:isa指针的含义

解释:

1.3.2、isa指向

1.4、cache_t

1.4.1、概念
1.4.2、结构

cache_t是一个结构体。


cache_t结构

可以理解为:

1.5、class_data_bits_t

1.5.1、class_rw_t

class_rw_t

1.5.2、class_ro_t

class_ro_t

1.5.3、method_t

method_t

1.5.3.1、Type Encodings

Type Encodings

实例分析:
-(void)aMethod;对应的Type Encodings
解析如下:

aMethod解析

注意:

1.6、整体数据结构

整体数据结构

二、对象、类对象、元类对象

2.1、概念

2.2、isa指针指向图

isa指针指向图

isa指针

superclass指针

问题3:类对象、元类对象分别是什么,有什么区别和联系?

问题4:如果说调用的一个类方法,没有对应的实现;但是,有同名的实例方法实现,会不会产生崩溃或者实际调用?

问题5:笔试题

笔试题
解释:

三、消息传递

3.1、函数介绍

void objc_msgSend(void /* id self, SEL op, ... */ )


消息传递

备注:

void objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )

Super 消息传递

备注:

3.2、消息传递流程

消息传递过程

四、消息传递三大步骤详解

4.1、缓存查找

给定值是SEL(方法选择器),目标值是对应的bucket_t中的IMP

缓存查找函数

4.2、当前类中查找

4.3、父类逐级查找

父类逐级查找

五、消息转发

消息转发

这里主要讲的是实例方法的转发流程。

5.1、(BOOL)resolveInstanceMethod:(SEL)sel

5.2、(id)forwardingTargetForSelector:(SEL)aSelector

5.3、(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector

5.4、(void)forwardInvocation:(NSInvocation *)anInvocation

六、Method-Swizzling

Method-Swizzling

主要代码如下:

//获取test方法
Method test = class_getInstanceMethod(self, @selector(test));
//获取otherTest方法
Method otherTest = class_getInstanceMethod(self, @selector(otherTest));
//交换两个方法的实现
method_exchangeImplementations(test, otherTest);

七、动态添加方法

class_addMethod(<#Class  _Nullable __unsafe_unretained cls#>, <#SEL  _Nonnull name#>, <#IMP  _Nonnull imp#>, <#const char * _Nullable types#>)

八、动态方法解析

问题6、你是否使用过@dynamic关键字?

解释:
也是借此考察运行时内容,因为使用@dynamic实际上是告诉编译器,自己来实现setter与getter方法,不自动生成。
这样声明的属性,即使你没有实现setter与getter方法,编译时,是不会报错的;但是当你使用到setter与getter方法时(运行时),就会报错。

问题7:编译时语言与运行时语言的区别?

解释:

问题8: [obj foo]和obj_msgSend()函数之间有什么关系?

解释:
在经过编译器转换之后,就变成了obj_msgSend(obj,@selector(foo)),然后就开始了消息传递过程。

问题9:runtime如何通过Selector找到对应的IMP地址的?

解释:
考察的是消息传递机制
查找当前实例对应类对象的缓存➡️查找类对象的方法列表➡️逐级查找父级方法列表。

问题10:能否向编译后的类增加实例变量?

解释:
考察的是runtime数据结构。
因为编译后的类,它已经完成了实例变量的布局,这个实例变量是存放在class_ro内部,这个是只读的,所以不能向编译后的类增加实例变量。
但是,可以向动态添加的类中添加实例变量。

问题11:函数调用与消息传递有怎样的区别?

解释:
考察消息传递机制

问题12:当我们调用一个方法没有实现的时候,系统是如何为我们实现消息转发过程的?

解释:
考察消息传递机制

上一篇 下一篇

猜你喜欢

热点阅读