美文网首页
32期_SDWebImage的缓存查找

32期_SDWebImage的缓存查找

作者: 萧修 | 来源:发表于2023-09-03 01:00 被阅读0次

涉及的类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

相关文章

网友评论

      本文标题:32期_SDWebImage的缓存查找

      本文链接:https://www.haomeiwen.com/subject/pwmfmdtx.html