1、Runtime消息转发机制?
1、Runtime是什么?
不严谨的说法:
1、运行时(Runtime)是指将数据类型的确定由编译时推迟到了运行时。
2、Runtime是一套比较底层的C语言API, 属于1个C语言库, 包含了很多底层的C语言API。
3、平时编写的OC代码,在程序运行过程中,其实最终会转换成Runtime的C语言代码,Runtime是Object-C的幕后工作者。
4、Object-C需要Runtime来创建类和对象,进行消息发送和转发。
较严谨说法:
1、将尽可能多的决策从编译时和链接时推迟到运行时。
2、运行时系统充当着Object-C语言的操作系统,它使语言能够工作。
3、Runtime编写的代码具有运行时、动态特性。
2、Runtime与OC的交互方式
1、通过Object-C源代码进行交互。
2、通过NSObject类中定义的方法交互。
3、通过直接调用运行时函数。
3、Runtime的作用以及常见用法
Runtime的作用:
1、在程序运行过程中,动态的创建类,动态添加、修改这个类的属性和方法。
2、遍历一个类中所有的成员变量、属性、以及所有方法。
3、消息传递、转发。
Runtime常见用法:
1、给系统分类添加属性、方法。
2、方法交换。
3、获取对象的属性、私有属性。
4、字典转换模型。
5、KVC、KVO。
6、归档(编码、解码)。
7、获取类名。
8、block。
...
4、Runtime定义
NSObject的定义:
@interface NSObject {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
Class isa OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
NSObject是一个Class类型来表示的指向objc_class结构体的指针。
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.
typedef struct objc_object *id;
id和Class指向的都是objc_class结构体
objc_class结构体中的定义:
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE;
const char * _Nonnull name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;
struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;
struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;
struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */
4、Runtime消息机制
在OC中所有调用的方法,都是Runtime通过objc_msgSend向这个类发送消息。
Objc-msgSend消息传递的过程:
1、消息发送给对象时,消息传递函数遵循对象的isa指针指向类结构的指针,在该结构中它查询结构体变量methodLists中的方法SEL
(方法选择器)。
2、如在isa指向的类结构中找不到SEL
(方法选择器),Objc_msgSend会跟随指向Supercalss(父类)指针并再次尝试查找该SEL
。
3、如连续失败直到NSObject类,它的superclass也就是它自己本身。
4、一旦找到SEL
,该函数就会调用methodLists的方法并将接收对象的指针传给它。
消息的加速发送:
有的时候在一个类会有继承关系,Objective-C中大部分对象都是继承于NSObject、自己自定义类,在这种继承体系当中有很多的方法,这些方法有可能不会用到,在向类发送消息的时候,去methodLists中查找无疑会拖慢程序的运行速度,所以Apple在开发的时候加入了cache的概念,也就是缓存。
在每个类中都会有一个单独的缓存,它可以包含继承过来的方法SEL
以及自己定义的SEL
,在搜索methodLists之前,消息传递程序会检查接受者对象的告诉缓存cache,如果找到,就不会再去搜索methodLists列表。
cache缓存的是一些已经调用过的SEL
,当写的程序预热足够时间,那么所有发送过的SEL
都会在cache中找到。
cache会动态增长,直到程序中所有调用的SEL
运行一遍为止。
5、Runtime消息转发
消息的传递过程中,当调用的对象的方法不存在时,会触发消息的转发机制。
消息转发过程:
1.动态方法解析
+(BOOL)resolveInstanceMethod:(SEL)sel 实例方法解析
+(BOOL)resolveClassMethod:(SEL)sel 类方法解析
当运用消息转发运行时,根据调用的方法类型调用这两个方法其中一个,返回值BOOL类型,告诉系统该消息是否被处理,YES处理 NO 未处理。
当这个对象在实现了resolveInstanceMethod,resolveClassMethod两个方法,并没有对该对象消息进行处理,那么该方法会被调用两次:
一次是没有找到该方法需要对象解析处理;第二次是告诉系统我处理完成需要再次调用该方法但实际上并没有处理完成,所以会调用第二次该方法崩溃。
2.后备接收者对象
-(id)forwardingTargetForSelector:(SEL)aSelector
在消息转发第一次方法解析中没有处理方法,并告诉系统本对象无法处理,需另寻办法,那么系统会给予另外一个办法,就是让别的对象B来处理该问题,如果对象B能够处理该消息,那么该消息转发结束。
3.以其他形式实现该消息方法
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
-(void)forwardInvocation:(NSInvocation *)anInvocation
当前面两个步骤都没有处理该SEL
时,就会到第三个步骤,这是最后寻找IML
的机会
将未知SEL作为参数传入methodSignatureForSelector
,在该方法中处理该消息,一旦能够处理,返回方法签名,让后续forwardInvocation
来进行处理。
forwardInvocation
可以直接切换调用目标,也就是该方法的Target
。
4.直到最后未处理,抛出异常
-(void)doesNotRecognizeSelector:(SEL)aSelector
作为找不到函数实现的最后一步,NSObject实现这个函数只有一个功能,就是抛出异常。
2、Runloop 让Runloop保活的方式?
3、SDWebImage的缓存原理以及沙盒中四个文件夹的区别(caches文件夹特点)?
1、SDWebImage的缓存原理
1、调用公开方法setImageWithURL:placeholderImage:options:
传入URL 开始处理图片。
2、先从内存图片缓存查找是否有图片,如果内存中已经有图片缓存,SDImageCacheDelegate
回调显示图片。
3、如果内存缓存中没有,生成 异步任务添加到队列,开始从硬盘查找图片是否已经缓存。
4、根据 URL的MD5值Key在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调 notifyDelegate:
。
5、如果从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小, 会先清空内存缓存)。SDImageCacheDelegate
回调展示图片。
6、如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片。
7、共享或重新生成一个下载器 SDWebImageDownloader
开始下载图片。
8、下载过程中利用 ImageIO做了按图片下载进度加载效果。
9、下载完成后做图片解码处理。
10、解码完成通知主线程解码完成并回调给SDWebImageDownloader
。
11、SDWebImageDownloader
回调给SDWebImageManager
通知下载完成。
12、SDWebImageManager
回调给需要的地方展示图片。
13、将图片同时保存到内存缓存和硬盘缓存中。
2、沙盒中四个文件夹的区别
1、Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。
2、 tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录。
3、 Library/Caches:保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据。
4、Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录。
4、KVO实现原理?
参考常见面试题一
5、TCP阻塞机制?
慢启动
拥塞规避
快速启动
快速恢复
6、http和https的区别?
7、自定义一个类A继承于NSObject 声明一个方法 不实现 写一个NSObject的分类去实现这个方法 调用时会不会出错 为什么 流程是什么?创建两个同一个类的分类 并声明同一个方法 会不会报错 为什么 怎么调用的?
都不会报错。
首先OC调用方法时 实际是通过消息传递来寻找方法的实现 A的最终方法的实现会找到最终的父类NSObject 遍历方法列表时 Runtime会把分类的方法添加到本类的方法列表中 所以最终会执行NSObject的分类方法 具体参考Runtime消息机制。
寻找方法实现时会把分类的方法合并到本类中,如果两个分类中有相同的方法,后编译的会覆盖掉先编译的方法。
8、内存管理方法?
9、为什么要用MVVM RAC数据双向绑定?
10、二分查找算法 以及时间复杂度?
11、控制器生命周期
12、有没有使用过分类 分类的优缺点是什么?
13、有没有写过动态库 动态库实现原理?
14、coreData和SQLite 几万条数据的查询优化(索引)?
15、图片压缩的一些方式?
16、视频编码格式原理?
17、GCD
向主队列添加的任务要等主线程中其他任务执行完毕再执行。