runtime面试题

1.你使用过Objective-C的运行时编程么?如果使用过,你用它做了什么?你还能记得你所使用的相关的头文件或者某些方法的名称吗?
NSObjCRuntime.h/NSObject.h/message.h/objc-api.h/objc-auto.h/objc-exception.h(异常操作)/objc-sync.h/objc.h(基本功能)/runtime.h(主要功能在runtime.h中)

2.runtime实现的机制是什么,怎么用,一般用于干嘛?
runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。平时编写的OC代码, 在程序运行过程中, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者。
runtime是属于OC的底层, 可以进行一些非常底层的操作(用OC是无法现实的, 不好实现)

  • 在程序运行过程中, 动态创建一个类(比如KVO的底层实现)
  • 在程序运行过程中, 动态地为某个类添加属性方法, 修改属性值
    遍历一个类的所有成员变量(属性)所有方法

3.kvo的实现原理是什么?
KVO是基于runtime机制实现的。
当某个类的对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法。
派生类在被重写的setter方法实现真正的通知机制(Person->NSKVONOtifying Person)
Person类对象p设置self控制器且设置监听属性,就会调用observeValueForKeyPath方法,当Person类的属性被改变时,就会动态生成一个子类继承自Person类(NSKVONotifying_Person),重写setAge方法,内部调用父类setAge方法,通知监听器
[监听器 observeValueForKeyPath:@"age" ofObject:self change:@{} context:(void *)context];
原先age属性不改变时p对象 isa指向Person,当age属性改变时p对象 isa指向NSKVONotifying_Person(setAge重新内部就会传递变量至父类且通知监听器age属性改变)

4.objc_setAssociatedObject、objc_getAssociatedObject是什么,有什么优点?
建立对象关联,使用关联,我们可以不用修改类的定义而为其对象增加存储空间。这在我们无法访问到类的源码的时候或者是考虑到二进制兼容性的时候是非常有用。
关联是基于关键字的,因此,我们可以为任何对象增加任意多的关联,每个都使用不同的关键字即可。关联是可以保证被关联的对象在关联对象的整个生命周期都是可用的(在垃圾自动回收环境下也不会导致资源不可回收)。

5.method swizzling是干什么的,一般用于哪里?
方法混用,可以通过runtime获取类的方法表。一个方法Method由三个部分组成SEL方法选标、IMP函数指针、typeEncode。可以直接class_replaceMethod替换原有方法,method_exchangeImplementations效果两个方法的实现或者method_setImplementation直接修改方法实现。
向视图控制器的生命周期中注入操作、事件的响应、视图的绘制,或Foundation中的网络堆栈都是能够利用method swizzling产生明显效果的场景。还有一些其他的场景使用swizzling会是一个合适的选择,这随着Objective-C开发者经验不断丰富会变得越来越明显。

6.可以向nil对象发送消息么?如果向一个nil对象发送消息将会发生什么?
在Objective-C中向nil发送消息是完全有效的——只是在运行时不会有任何作用。

7.category,method 的实现机制是什么?
根据苹果官方文档对 Category 的描述,它的使用场景主要有三个:
给现有的类添加方法;
将一个类的实现拆分成多个独立的源文件;无论我们有没有主动引入 Category 的头文件,Category 中的方法都会被添加进主类中。将 Category 和它的主类(或元类)注册到哈希表中;
如果主类(或元类)已实现,那么重建它的方法列表。
在这里分了两种情况进行处理:Category 中的实例方法和属性被整合到主类中;而类方法则被整合到元类中。将 Category 中的方法、属性和协议整合到类(主类或元类)中,更新类的数据字段 data() 中 method_lists(或 method_list) 、 properties 和 protocols 的值。

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

9.objc使用什么机制管理对象内存?
通过 retainCount 的机制来决定对象是否需要释放。 每次 runloop 的时候,都会检查对象的 retainCount,如果retainCount 为 0,说明该对象没有地方需要继续使用了,可以释放掉了。

10.为什么说Object-C是runtime language? runtime有什么优点?
将数据类型的确定由编译时,推迟到了运行时。运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。实现多态,不同对象以自己的方式响应相同的消息的能力。

11.什么是动态,举例说明

OC具有很多的动态特性,有动态类型(Dynamic typing),动态绑定(Dynamic binding)和动态加载(Dynamic loading).OC在底层也提供了相当丰富的运行时特性,比如枚举类属性方法,获取方法实现等.
动态特性 :
动态类型:即运行时再决定对象的类型.id类型即通用的对象类,任何的对象都可以用id类型来指向(通常用于不知道该对象为什么类型的对象的时候才使用).
id obj = name;
if ([obj isKindOfClass:[NSString class]]) {
NSString * str = (NSString *)name;
}
isKindOfClass:用于确定某个NSObject对象是否是某个类的成员. 而isMemberOfClass:是NSObject方法,用于确定某个对象是否是某个类或其子类的成员
动态绑定:经过动态类型确定实例对象之后,该实例对象对应的属性和一些方法也随即被确定,根据类的确定,确定了类的属性和类的方法.OC中调用一个实例的方法,就是通过OC的消息机制发送一个消息,实例在收到消息后,从自身的实现中找到方法来响应.动态绑定就是实例所属的类经过运行后确定,将类的属性和方法绑定在动态类型上,而不是实现确定的,因为类也是动态类型的
动态加载:所谓动态加载就是我们做开发的时候icon图片的时候在Retina设备上要多添加一个张@2x的图片,当设备更换的时候,图片也会自动的替换,还有就是我们公司主板项目中根据服务器返回的类名来动态创建类.
iOS开发的运行时特性
我们做开发的时候会经常用到Protocol-Delegate的设计模式,所以不管是我们使用的,还是我们自己定义的delegate指针类型必须是id类型的,只有这样我们才能够满足程序运行时delegate的来回切换.

12.runtime有啥用?
1>能动态产生一个类、一个成员变量、一个方法
2>能动态修改一个类、一个成员变量、一个方法
3>能动态删除一个类、一个成员变量、一个方法
其常见的函数、头文件

import : 成员变量、类、方法

class_copyIvarList : 获得某个类内部的所有成员变量
class_copyMethodList : 获得某个类内部的所有方法
class_getInstanceMethod : 获得某个具体的实例方法(对象方法,减号开头)
class_getClassMethod : 获得某个具体的类方法 (加号)
method_exchangeImplementations : 交换2个方法的实现

import 消息机制

objc_msgSend(...);
runtime可以实现遍历所有成员变量,使用runtime机制,某类交换2个方法的实现交换2个方法的好处:以后一个大项目当中的一个方法使用过多,想动一些手脚和操作,就可以很方便实现。

你可能感兴趣的:(runtime面试题)