涉及的类SDImageCache
,可从SDWebImageManager
入手
为其一个属性。所有图片加载都通过这个。
@interface SDWebImageManager : NSObject
@property (strong, nonatomic], readonly, nonnull) id<SDImageCache> imageCache;
@end
SDImageCache
@interface SDImageCache : NSObject
@property (nonatomic, copy, nonnull, readonly) SDImageCacheConfig *config;
@property (nonatomic, strong, readonly, nonnull) id<SDMemoryCache> memoryCache;
@property (nonatomic, strong, readonly, nonnull) id<SDDiskCache> diskCache;
@end
缓存策略
@interface SDImageCacheConfig : NSObject <NSCopying>
@property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
@property (assign, nonatomic) BOOL shouldUseWeakMemoryCache;
@end
该类有内存缓存和磁盘缓存两种
SDMemoryCache.m
- (nullable SDImageCacheToken *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options context:(nullable SDWebImageContext *)context cacheType:(SDImageCacheType)queryCacheType done:(nullable SDImageCacheQueryCompletionBlock)doneBlock {
if (!key) {
if (doneBlock) {
doneBlock(nil, nil, SDImageCacheTypeNone);
}
return nil;
}
// Invalid cache type
if (queryCacheType == SDImageCacheTypeNone) {
if (doneBlock) {
doneBlock(nil, nil, SDImageCacheTypeNone);
}
return nil;
}
// First check the in-memory cache...
UIImage *image;
if (queryCacheType != SDImageCacheTypeDisk) {
image = [self imageFromMemoryCacheForKey:key];
}
是否仅仅读取内存,仅仅读取磁盘等判断
之后加载磁盘
...
NSData* (^queryDiskDataBlock)(void) = ^NSData* {
@synchronized (operation) {
if (operation.isCancelled) {
return nil;
}
}
return [self diskImageDataBySearchingAllPathsForKey:key];
};
}
imageFromMemoryCacheForKey
标志要从内存读取,当查不到时,
diskImageDataBySearchingAllPathsForKey
标志从磁盘读取
内存缓存
- SDMemoryCache
@interface SDMemoryCache <KeyType, ObjectType> : NSCache <KeyType, ObjectType> <SDMemoryCache>
@property (nonatomic, strong, nonnull, readonly) SDImageCacheConfig *config;
@end
- imageFromMemoryCacheForKey
SDImageCache.m
- (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key {
return [self.memoryCache objectForKey:key];
}
- objectForKey
SDMemoryCache.m
- (id)objectForKey:(id)key {
id obj = [super objectForKey:key];
if (!self.config.shouldUseWeakMemoryCache) {
return obj;
}
if (key && !obj) {
// Check weak cache
SD_LOCK(_weakCacheLock);
obj = [self.weakCache objectForKey:key];
SD_UNLOCK(_weakCacheLock);
if (obj) {
// Sync cache
NSUInteger cost = 0;
if ([obj isKindOfClass:[UIImage class]]) {
cost = [(UIImage *)obj sd_memoryCost];
}
[super setObject:obj forKey:key cost:cost];
}
}
return obj;
}
磁盘缓存
@interface SDDiskCache : NSObject <SDDiskCache>
@property (nonatomic, strong, readonly, nonnull) SDImageCacheConfig *config;
- (nonnull instancetype)init NS_UNAVAILABLE;
- (void)moveCacheDirectoryFromPath:(nonnull NSString *)srcPath toPath:(nonnull NSString *)dstPath;
@end
- diskImageDataBySearchingAllPathsForKey
- (nullable NSData *)diskImageDataBySearchingAllPathsForKey:(nullable NSString *)key {
if (!key) {
return nil;
}
NSData *data = [self.diskCache dataForKey:key];
if (data) {
return data;
}
// Addtional cache path for custom pre-load cache
if (self.additionalCachePathBlock) {
NSString *filePath = self.additionalCachePathBlock(key);
if (filePath) {
data = [NSData dataWithContentsOfFile:filePath options:self.config.diskCacheReadingOptions error:nil];
}
}
return data;
}
- dataForKey
- (NSData *)dataForKey:(NSString *)key {
NSParameterAssert(key);
NSString *filePath = [self cachePathForKey:key];
NSData *data = [NSData dataWithContentsOfFile:filePath options:self.config.diskCacheReadingOptions error:nil];
if (data) {
return data;
}
// fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name
// checking the key with and without the extension
data = [NSData dataWithContentsOfFile:filePath.stringByDeletingPathExtension options:self.config.diskCacheReadingOptions error:nil];
if (data) {
return data;
}
return nil;
}
- cachePathForKey
- (nullable NSString *)cachePathForKey:(NSString *)key {
NSParameterAssert(key);
return [self cachePathForKey:key inPath:self.diskCachePath];
}
- cachePathForKey:inPath
- (nullable NSString *)cachePathForKey:(nullable NSString *)key inPath:(nonnull NSString *)path {
NSString *filename = SDDiskCacheFileNameForKey(key);
return [path stringByAppendingPathComponent:filename];
}
SDDiskCacheFileNameForKey为磁盘中MD5转换
磁盘缓存查找用到了gcd
内存缓存和磁盘缓存执行完毕之后,还会进入下载涉及的类SDImageLoader
网友评论