sdwebimage
SDWebImage 如何区分图片格式?
将数据data转为十六进制数据,取第一个字节数据进行判断
SDWebImage 缓存图片的名称如何避免重名
对『绝对路径』进行MD5
SDWebImage 如何保证UI操作放在主线程中执行?
// SDWebImageCompat.h 中
#ifndef dispatch_main_async_safe
#define dispatch_main_async_safe(block)\
if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {\
block();\
} else {\
dispatch_async(dispatch_get_main_queue(), block);\
}
#endif
分析:如何判断当前是否在main thread?
某些api不仅依赖于主线程上的运行,而且还依赖于主队列,因此检查当前队列而不是检查当前线程更安全。
GCD没有一个非常方便的API来检查我们当前正在运行的队列(这很可能是许多开发人员首先使用NSThread.isMainThread()的原因)。
我们需要使用 dispatch_queue_set_specific 函数来将键值对与主队列相关联;稍后,我们可以使用 dispatch_queue_get_specific 来检查键和值的存在。
更安全的方法二 (SDWebImage使用的方法)
我们知道在使用 GCD 创建一个 queue 的时候会指定 queue_label,可以理解为队列名,就像下面:
dispatch_queue_t myQueue = dispatch_queue_create
("com.apple.threadQueue", DISPATCH_QUEUE_SERIAL);
而第一个参数就是 queue_label,根据官方文档解释,这个queueLabel 是唯一的,所以SDWebImage就采用了这个方式
//取得当前队列的队列名
dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)
//取得主队列的队列名
dispatch_queue_get_label(dispatch_get_main_queue())
然后通过 strcmp 函数进行比较,如果为0 则证明当前队列就是主队列。
SDWebImage 的Memory缓存和Disk缓存是用什么实现的?
Memory缓存实现 -- AutoPurgeCache
AutoPurgeCache』类继承自 『NSCache』
Disk缓存实现 -- NSFileManager
SDImageCache 的磁盘缓存是通过异步操作 NSFileManager 存储缓存文件到沙盒来实现的。
读取Memory和Disk的时候如何保证线程安全?
读取Memory
NScache是线程安全的,在多线程操作中,不需要对Cache加锁。
读取缓存的时候是在主线程进行。由于使用NSCache进行存储、所以不需要担心单个value对象的线程安全。
读取Disk
- 创建了一个名为 IO的串行队列,所有Disk操作都在此队列中,逐个执行!!
@property (SDDispatchQueueSetterSementics,
nonatomic, nullable) dispatch_queue_t ioQueue;
// Create IO serial queue
_ioQueue = dispatch_queue_create("com.hackemist.SDWebImageCache",
DISPATCH_QUEUE_SERIAL);
- 判断当前是否是IOQueue
- (void)checkIfQueueIsIOQueue {
const char *currentQueueLabel = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL);
const char *ioQueueLabel = dispatch_queue_get_label(self.ioQueue);
if (strcmp(currentQueueLabel, ioQueueLabel) != 0) {
NSLog(@"This method should be called from the ioQueue");
}
}
网友评论