iOS 第三方源码解析

SDWebImage

首先SDWebImage是我们经常用的一个加载网络图片的库,内部很好的处理了缓存、下载、解码之间关系,使得在性能上有很大的提升。
SDWebImage大致可以分为5大块:
我们拿UIImageView来说,入口就是

[imageView sd_setImageWithURL:nil]
  1. wrap结构:充分使用了单一原则和接口隔离的设计原则,UIImageView跟UIButton等空间区分开来,互相不干扰。但是他们都会走到UIView的 sd_internalSetImageWithURL方法,在这里处理相关逻辑。
  2. 管理:使用SDImageManage类来调节缓存跟回调之间的关系。当接收到此URL,会先进行取消下载,避免多次下载。作用就是调度缓存下载外层结构之间的关系回调
  3. 缓存:然后sd_queryCacheOperationForKey内部寻找缓存,先根据NSCache在内存中查找是否存在缓存,然后在磁盘中查找缓存,这里有个小细节就是,如果在磁盘中查到缓存就将缓存存入内存中去,如果两个都没有找到需要进行下载。
  4. 下载:使用SDImageOperationQuque来进行管理下载,创建一个任务,启动section进行下载,通知管理类,来处理图片。
  5. 解码:网络图片一般会偏大,对于我们的图片渲染性能来说是个很大的损失,所以这里讲图片进行解码操作,生成位图返回新图片,这样在GPU渲染的时候可以直接使用位图来进行渲染,极大的提升性能。
    然后异步将图片存入缓存之中去。清除缓存的时候时候会将默认1周的图片进行清理,避免浪费空间。

总结:通过源码学到了作者的编程思想,设计原则体现的淋漓尽致,将类于类之间充分的解耦,枚举使用位移的方式,节省内存开销。下载使用Operation队列来管理下载类,对自己以后做下载相关需求的时候很大的提升,缓存的思维,内存报警之后的处理。图片的解码了解到性能上的优化相关的操作等等。

YYCache

YYCache是我们通常使用的缓存类,当我们做页面缓存的时候是一个非常不错的选择。
缓存分为2类,一种是内存缓存,一种是磁盘缓存

  1. 内存缓存:YYMeroryCache
    适用于体积小,速度快。内部实现了LRU(缓存淘汰算法),使用双向链表来存储。
    LRU的实现:淘汰访问频率低的节点,当存入一个新节点就放置头部,放存入一个已经存在的节点就把当前节点拿出来放置头部。删除的时候从链表尾端开始删除。
    链表采用C语言的字典来实现,节点内部元素有parentNode、childNode,缓存开销等变量。采用pthread_mutex_lock锁的机制来处理资源访问的时候线程安全。
  2. 磁盘缓存: YYDiskCache
    适用于体积大,相对来说速度慢。
    使用YYKVStore来管理对文件的操作,磁盘缓存分2种,一种是数据库存储,一种是数据库/文件混合存储
    当资源>20KB的时候会采用混合存储,此时数据的元数据存在sqlite3数据库中,数据存在文件系统中去。采用信号量对资源进行加锁。
    总结:YYCache的设计流程:先内存后磁盘,双重实现来对数据的缓存,LRU算法,双向链表的使用。
    磁盘缓存使用数据库跟文件混合存储,性能上极大的提升。
    使用pthread_metux_lock和信号量分别的不同的方式进行线程安全的维护。他们的区别在于信号量在等待的时候性能优于pthread_metux_lock,等待的时候不消耗CPU。而且信号量在处理线程等待的时候会对线程进行顺序进行,而pthread_metux_lock等待的时候是无序的。

Masorny

Masorny是一个可以对屏幕进行适配一个轻量级的布局架构,他是封装了系统的AutoLayout来实现的。内部使用了链式编程的风格,点语法,可以循环式调用自身,增加了diamante的可读性,优化了代码风格。MASConstraintMaker是一个工厂类。
总结:链式编程思想,使用点语法,隐式block回调。

WebViewJavaScriptBridge

WebViewJavaScriptBridge是H5跟OC交互的一个常用的库。

  1. 初始化:在OC端初始化bridge,H5端写入setupJavascript方法,创建一个iframe标签,设置scr为“https://bridge_loaded”,注入JS脚本,webview的代理方法webView:decidePolicyForNavgationAction:...方法可以检测到。
  2. OC调用H5:调用callHandle方法,base调用sendData方法,封装一个唯一的消息id,存在本地。接着调用,将消息json序列化,webview注入JS,执行H5中对应的handleName的方法回调。
    3.H5调用OC:H5端调用callHandle,本地调用registerHandle,将handleName存入字典。H5调用callHandle,触发注入的JS代码中的callHandle方法,内部调用__doSend方法,将iframe的scr重新改写,这时webView的webview:decidePolicyForNavgationAction代理方法,根据handleName找到存储在本地的messageQueue的block,执行block,调用OC的方法。
    总结:OC通过webview执行JS代码,来通知H5,触发回调。H5通过iframe标签设置scr,然后webView的decidePolicyForNavgationAction方法接收到响应,触发回调方法。