1.SDWebImage、AFNetWorking底层原理;
1.SDWebImage工作流程
1、入口 setImageWithURL:placeholderImage:options: 会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始处理图片。
2、进入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交给 SDImageCache 从缓存查找图片是否已经下载 queryDiskCacheForKey:delegate:userInfo:.
3、先从内存图片缓存查找是否有图片,如果内存中已经有图片缓存,SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。
4、SDWebImageManagerDelegate 回调 webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示图片。
5、如果内存缓存中没有,生成 NSInvocationOperation 添加到队列开始从硬盘查找图片是否已经缓存。
6、根据 URLKey 在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调 notifyDelegate:。
7、如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:。进而回调展示图片。
8、如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调 imageCache:didNotFindImageForKey:userInfo:。
9、共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。
10、图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。
11、connection:didReceiveData: 中利用 ImageIO 做了按图片下载进度加载效果。connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。
12、图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。
13、在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给 SDWebImageDownloader。imageDownloader:didFinishWithImage: 回调给 SDWebImageManager 告知图片下载完成。
14、通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。写文件到硬盘也在以单独 NSInvocationOperation 完成,避免拖慢主线程。
15、SDImageCache 在初始化的时候会注册一些消息通知,在内存警告或退到后台的时候清理内存图片缓存,应用结束的时候清理过期图片。
16、SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。
17、SDWebImagePrefetcher 可以预先下载图片,方便后续使用。
2.AFNetWorking底层原理;
2.OC内存管理
参考1:www.jianshu.com/p/0d7dfb509…
参考2:www.jianshu.com/p/22031a104…
内存五大区:www.jianshu.com/p/e5a54813b…
3.KVC、KVO实现原理
参考:www.jianshu.com/p/aab515490… zhuanlan.zhihu.com/p/159206464
4.MVC、MVVM设计模式;
mvvm设计模式
- model(数据模型),view(视图),viewmodel(视图模型)
- 大家可以看到,里面是没有controller了,但是他将viewmodel代替了controller。在运行过程中起了view和 model的链接桥梁,但是又有一点区别与mvc的是,mvc中被动接受view请求的controller在这里,viewmodel给他做了升级,不再是被动接受,而是不断监听view,当有新的需求时,就去链接model拿去数据,然后返回给页面,很好的将view和model做了分离,使view和viewmodel可以独立完成开发。
- 缺点:不断的监听页面,性能消耗很大
mvc和mvvm的区别
- mvc中controller是被动接受请求,而mvvm中作为控制器这一环节的是主动地。
- mvc中view可以直接访问model,因此view中必然包含了业务逻辑,并没有实现view和model的分离,而mvvm主要是通过数据的双向绑定机制,在js中实现业务逻辑,进行view和model的关联,因此mvvm真正意义上实现了view和model的分离。
5.runtime、runloop
1.讲一下 OC 的消息机制
- OC中的方法调用其实都是转成了objc_msgSend函数的调用,给receiver(方法调用者)发送了一条消息(selector方法名)
- objc_msgSend底层有3大阶段
- 消息发送(当前类、父类中查找)、动态方法解析、消息转发
2.什么是runtime
- OC 是一个全动态语言,OC 的一切都是基于 Runtime 实现的平时编写的OC代码, 在程序运行过程中, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者 比如:
OC :
[[Person alloc] init]
runtime :
objc_msgSend(objc_msgSend("Person" , "alloc"), "init")
- runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API
- runtimeAPI的实现是用 C++ 开发的(源码中的实现文件都是mm),是一套苹果开源的框架
3.runtime具体应用
- 利用关联对象(AssociatedObject)给分类添加属性
- 遍历类的所有成员变量(修改textfield的占位文字颜色、字典转模型、自动归档解档)
- 交换方法实现(交换系统的方法)
- 利用消息转发机制解决方法找不到的异常问题
Runloop
RunLoop运行流程
没有事情的时候,Runloop处于休眠状态。当外部source将其唤醒后,它会依次处理接收到的timer/source,然后再次进入休眠。
一个Runloop可能有几个mode
- 指定事件在运行循环中的优先级的
- 线程的运行需要不同的模式,去响应各种不同的事件,去处理不同情境模式。(比如可以优化tableview的时候可以设置UITrackingRunLoopMode下不进行一些操作,比如设置图片等。)
Runloop Mode 实际上是 Source,Timer 和 Observer 的集合,不同的 Mode 把不同组的Source,Timer和Observer隔绝开来。Runloop` 在某个时刻只能跑在一个 Mode 下,处理这一个 Mode 当中的 Source,Timer 和 Observer。
苹果文档中提到的 Mode 有五个,分别是:
NSDefaultRunLoopMode:默认的mode,正常情况下都是在这个mode
NSConnectionReplyMode
NSModalPanelRunLoopMode
NSEventTrackingRunLoopMode:使用这个Mode去跟踪来自用户交互的事件(比如UITableView上下滑动)
NSRunLoopCommonModes
iOS 中公开暴露出来的只有 NSDefaultRunLoopMode 和 NSRunLoopCommonModes。 NSRunLoopCommonModes 实际上是一个 Mode 的集合,默认包括 NSDefaultRunLoopMode 和 NSEventTrackingRunLoopMode。
Source
即可以唤醒Runloop的一些事件。比如用户点击了屏幕,就会创建一个input source。
source0: 非系统事件source1: 系统时间
Timer
我们经常用的NSTimer就属于这一类。
Observer
某个observer可以监听runloop的状态变化,并作出一定反应。
什么是Runloop
Runloop是事件接收和分发机制的一个实现。是线程相关的基础框架的一部分。一个Runloop就是一个事件处理的循环,用来不停的调度工作及处理输入事件。使用runloop的目的就是让你的线程不会被系统终止
RunLoop的主要目的:
保证程序执行的线程不会被系统终止,如果没有RunLoop,UIApplicationMain函数执行完毕之后将直接返回,就是说程序一启动然后就结束,在有工作的时候忙于工作,而没有工作的时候处于休眠状态,
Runloop和线程是什么关系?
每条线程都有唯一的一个与之对应的RunLoop对象;主线程的RunLoop已经自动创建,子线程的RunLoop需要主动创建;RunLoop在第一次获取时创建,在线程结束时销毁
什么时候使用Runloop ?
当需要和该线程进行交互的时候才会使用Runloop.
RunLoop处理消息的流程是“接收消息->恢复活跃->处理消息->进入休眠”。
RunLoop怎么用?
1.NSTimer中底层用到了RunLoop。
2.Autorelerasepool也是用了RunLoop的原理进行内存的回收
3.创建NSTimer的时候,也是用到了RunLoop,performSelecter:afterDelay使用时。
4.事件的交互,触摸屏幕或者硬件的交互,也用到了RunLoop。
5.UI界面刷新。
6.调用了dispatch_async(dispatch_get_main_queue(), block)时,主队列会把该 block 放到对应的线程(恰好是主线程)中,主线程的 RunLoop 会被唤醒。
7.AFNetWorking 3.0以前的线程保活。
8.可以用来监控系统卡顿。
6.Https
7.Block
参考1:www.jianshu.com/p/4e79e9a0d…
参考2:www.jianshu.com/p/0a555501a…
学习:www.jianshu.com/p/5afb47cf5…
8.多线程(GCD、NSThread)
GCD参考:www.jianshu.com/p/2d57c7201…
NSThread参考:www.jianshu.com/p/9ae8e7a18… 线程间的通信:cloud.tencent.com/developer/a…
常驻线程:blog.csdn.net/u012094456/… 线程与进程关系:blog.csdn.net/u012094456/…
9.锁
八种锁:www.jianshu.com/p/8b8a01dd6…
简介及使用:www.jianshu.com/p/af7ff3862…
锁的原理:www.jianshu.com/p/494629e92…
10.组件化解决方案
组件方案:www.jianshu.com/p/7ca16c92c…
组件通信:www.jianshu.com/p/1f10795c9…
组件化通讯方案
目前主流的主要有以下三种方式:
- 1、
URL路由 - 2、
target-action - 3、
protocol匹配
11.dyld
12.优化
性能优化:
界面优化:www.jianshu.com/p/5c83da126…
13.视觉效果
视觉效果处理:www.jianshu.com/p/5445fb11e…