SDWebImage中的SDImageCache、SDImageCacheConfig

一、概念介绍

SDWebImageCache是SDWebImage中的一个缓存类,是拿来缓存数据的,在SDWebImage中分为缓存数据到磁盘以及内存,下面就简单的介绍下它们头文件的内容,其实它们的头文件的内容就是给我们在外面可以自定义去设置的,可以去调用头文件的方法,本身就是这个框架对外的接口,所以我们应该对其的概念应该有一定的了解

二、代码实战

关于SDImageCache.h文件的内容

#import <Foundation/Foundation.h>
#import "SDWebImageCompat.h"
#import "SDImageCacheConfig.h"

//SDImageCacheType主要是拿来做通知的回调,拿到图片的时候,SDWebImage会告诉我们是从磁盘中来还是内存
typedef NS_ENUM(NSInteger, SDImageCacheType) {
    /**
     * The image wasn't available the SDWebImage caches, but was downloaded from the web.
     //没有缓存,图片直接从网络上下载过来
     */
    SDImageCacheTypeNone,
    /**
     * The image was obtained from the disk cache.
     图片从磁盘中获取
     */
    SDImageCacheTypeDisk,
    /**
     * The image was obtained from the memory cache.
     图片从内存中来
     */
    SDImageCacheTypeMemory
};

typedef NS_OPTIONS(NSUInteger, SDImageCacheOptions) {
    /**
     * By default, we do not query disk data when the image is cached in memory. This mask can force to query disk data at the same time.
     默认情况下,当图像有缓存到内存中时,我们不会查询磁盘数据。这个选项可以同时强制查询磁盘数据。
     */
    SDImageCacheQueryDataWhenInMemory = 1 << 0,
    /**
     * By default, we query the memory cache synchronously, disk cache asynchronously. This mask can force to query disk cache synchronously.
     默认情况下,我们同步查询内存缓存,异步的查询磁盘缓存。此掩码可以同步查询磁盘缓存。
     */
    SDImageCacheQueryDiskSync = 1 << 1
};
//查询完毕的block,会把图片和图片的data以及从那边来的回调过去,会传入这个image是从网络上来的,还是磁盘还是内存

typedef void(^SDCacheQueryCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType);

//判断是否有缓存的回调
typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache);

//计算文件的大小和文件的数量
typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger totalSize);


/**
 * SDImageCache maintains a memory cache and an optional disk cache. Disk cache write operations are performed
 * asynchronous so it doesn’t add unnecessary latency to the UI.
 */
@interface SDImageCache : NSObject

#pragma mark - Properties

/**
 *  Cache Config object - storing all kind of settings
    缓存配置对象  
 */
@property (nonatomic, nonnull, readonly) SDImageCacheConfig *config;

/**
 * The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory.
 //设置缓存中最大的消耗的内存,这里计算的是内存中的像素个数
 */
@property (assign, nonatomic) NSUInteger maxMemoryCost;

/**
 * The maximum number of objects the cache should hold.
 缓存应该持有的对象的最大数量
 */
@property (assign, nonatomic) NSUInteger maxMemoryCountLimit;

#pragma mark - Singleton and initialization

/**
 * Returns global shared cache instance
 * 返回全局共享缓存实例
 * @return SDImageCache global instance
 */
+ (nonnull instancetype)sharedImageCache;

/**
 * Init a new cache store with a specific namespace
 * 初始化一个新的缓存命名空间,里面就是去获取磁盘缓存路径,然后再进行一系列的初始化操作
 * @param ns The namespace to use for this cache store
 */
- (nonnull instancetype)initWithNamespace:(nonnull NSString *)ns;

/**
 * Init a new cache store with a specific namespace and directory
 * 用命名空间和路径初始化一个新的缓存路径
 * @param ns        The namespace to use for this cache store
 * @param directory Directory to cache disk images in
 */
- (nonnull instancetype)initWithNamespace:(nonnull NSString *)ns
                       diskCacheDirectory:(nonnull NSString *)directory NS_DESIGNATED_INITIALIZER;

#pragma mark - Cache paths

//初始化磁盘缓存路径
- (nullable NSString *)makeDiskCachePath:(nonnull NSString*)fullNamespace;

/**
 * Add a read-only cache path to search for images pre-cached by SDImageCache
 * Useful if you want to bundle pre-loaded images with your app
 *添加一个只读缓存路径,由SDImageCache搜索已经预缓存的图像。
  如果你想把预装的图片和你的应用捆绑在一起,这很有用。去找图片就也可以在这个路径中进行添加
 * @param path The path to use for this read-only cache path
 */
- (void)addReadOnlyCachePath:(nonnull NSString *)path;

#pragma mark - Store Ops

/**
 * Asynchronously store an image into memory and disk cache at the given key.
 * 根据key异步的存储图片到磁盘中然后还要存储在内存中
 * @param image           The image to store
 * @param key             The unique image cache key, usually it's image absolute URL
 * @param completionBlock A block executed after the operation is finished
 */
- (void)storeImage:(nullable UIImage *)image
            forKey:(nullable NSString *)key
        completion:(nullable SDWebImageNoParamsBlock)completionBlock;

/**
 * Asynchronously store an image into memory and disk cache at the given key.
 * 根据toDisk来判断是否要存储到磁盘中,也就是说这里的磁盘缓存是可选的
 * @param image           The image to store
 * @param key             The unique image cache key, usually it's image absolute URL
 * @param toDisk          Store the image to disk cache if YES
 * @param completionBlock A block executed after the operation is finished
 */
- (void)storeImage:(nullable UIImage *)image
            forKey:(nullable NSString *)key
            toDisk:(BOOL)toDisk
        completion:(nullable SDWebImageNoParamsBlock)completionBlock;

/**
 * Asynchronously store an image into memory and disk cache at the given key.
 * 这里面的方法会根据imageData如果没有,但是image有的话,就会考虑到图片格式的问题
 * @param image           The image to store
 * @param imageData       The image data as returned by the server, this representation will be used for disk storage
 *                        instead of converting the given image object into a storable/compressed image format in order
 *                        to save quality and CPU
 * @param key             The unique image cache key, usually it's image absolute URL
 * @param toDisk          Store the image to disk cache if YES
 * @param completionBlock A block executed after the operation is finished
 */
- (void)storeImage:(nullable UIImage *)image
         imageData:(nullable NSData *)imageData
            forKey:(nullable NSString *)key
            toDisk:(BOOL)toDisk
        completion:(nullable SDWebImageNoParamsBlock)completionBlock;

/**
 * Synchronously store image NSData into disk cache at the given key.
 * 根据key保存图片的data,给保存到磁盘缓存中
 * @warning This method is synchronous, make sure to call it from the ioQueue
 *
 * @param imageData  The image data to store
 * @param key        The unique image cache key, usually it's image absolute URL
 */
- (void)storeImageDataToDisk:(nullable NSData *)imageData forKey:(nullable NSString *)key;

#pragma mark - Query and Retrieve Ops

/**
 *  Async check if image exists in disk cache already (does not load the image)
 * 根据key判断是否Image是否存在磁盘中:异步处理,回调返回结果
 *  @param key             the key describing the url
 *  @param completionBlock the block to be executed when the check is done.
 *  @note the completion block will be always executed on the main queue
 */
- (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock;

/**
 *  Sync check if image data exists in disk cache already (does not load the image)
 * 根据key判断image是否存在磁盘中:同步处理,直接返回结果
 *  @param key             the key describing the url
 */
- (BOOL)diskImageDataExistsWithKey:(nullable NSString *)key;

/**
 * Operation that queries the cache asynchronously and call the completion when done.
 * 操作以异步方式查询缓存,并在完成时调用done。
 * @param key       The unique key used to store the wanted image
 * @param doneBlock The completion block. Will not get called if the operation is cancelled
 *
 * @return a NSOperation instance containing the cache op
 */
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock;

/**
 * Operation that queries the cache asynchronously and call the completion when done.
 * 操作以异步方式查询缓存,并在完成时调用done 这里可以传入options
 * @param key       The unique key used to store the wanted image
 * @param options   A mask to specify options to use for this cache query
 * @param doneBlock The completion block. Will not get called if the operation is cancelled
 *
 * @return a NSOperation instance containing the cache op
 */
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options done:
(nullable SDCacheQueryCompletedBlock)doneBlock;

/**
 * Query the memory cache synchronously.
 * 根据key从内存中获取图片
 * @param key The unique key used to store the image
 */
- (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key;

/**
 * Query the disk cache synchronously.
 * 据key判断是否Image是否存在磁盘中:同步处理
 * @param key The unique key used to store the image
 */
- (nullable UIImage *)imageFromDiskCacheForKey:(nullable NSString *)key;

/**
 * Query the cache (memory and or disk) synchronously after checking the memory cache.
 *根据key从磁盘缓存或者是内存中获取图片
 * @param key The unique key used to store the image
 */
- (nullable UIImage *)imageFromCacheForKey:(nullable NSString *)key;

#pragma mark - Remove Ops

/**
 * Remove the image from memory and disk cache asynchronously
 * 根据key从内存和磁盘删除缓存图片,异步处理
 * @param key             The unique image cache key
 * @param completion      A block that should be executed after the image has been removed (optional)
 */
- (void)removeImageForKey:(nullable NSString *)key withCompletion:(nullable SDWebImageNoParamsBlock)completion;

/**
 * Remove the image from memory and optionally disk cache asynchronously
 * 根据key删除缓存图片,可以指定是否从磁盘删除,回调通知
 * @param key             The unique image cache key
 * @param fromDisk        Also remove cache entry from disk if YES
 * @param completion      A block that should be executed after the image has been removed (optional)
 */
- (void)removeImageForKey:(nullable NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(nullable SDWebImageNoParamsBlock)
completion;

#pragma mark - Cache clean Ops

/**
 * Clear all memory cached images
 清空内存缓存图片
 */
- (void)clearMemory;

/**
 * Async clear all disk cached images. Non-blocking method - returns immediately.
 异步清空磁盘的所有缓存图片,并回调通知
 * @param completion    A block that should be executed after cache expiration completes (optional)
 */
- (void)clearDiskOnCompletion:(nullable SDWebImageNoParamsBlock)completion;

/**
 * Async remove all expired cached image from disk. Non-blocking method - returns immediately.
    异步的去磁盘清理过期的缓存数据
 * @param completionBlock A block that should be executed after cache expiration completes (optional)
 */
- (void)deleteOldFilesWithCompletionBlock:(nullable SDWebImageNoParamsBlock)completionBlock;

#pragma mark - Cache Info

/**
 * Get the size used by the disk cache
 同步操作:获取缓存中所有文件的大小
 */
- (NSUInteger)getSize;

/**
 * Get the number of images in the disk cache
 同步操作:获取磁盘缓存中图片数
 */
- (NSUInteger)getDiskCount;

/**
 异步操作:获取缓存中图片数及图片所占内存总大小
 * Asynchronously calculate the disk cache's size.
 */
- (void)calculateSizeWithCompletionBlock:(nullable SDWebImageCalculateSizeBlock)completionBlock;

#pragma mark - Cache Paths

/**
 *  Get the cache path for a certain key (needs the cache path root folder)
 *  需要根路径和key来查询文件所在的位置
 *  @param key  the key (can be obtained from url using cacheKeyForURL)
 *  @param path the cache path root folder
 *
 *  @return the cache path
 */
- (nullable NSString *)cachePathForKey:(nullable NSString *)key inPath:(nonnull NSString *)path;

/**
 *  Get the default cache path for a certain key
 *  根据key获取相应文件的默认的缓存路径
 *  @param key the key (can be obtained from url using cacheKeyForURL)
 *
 *  @return the default cache path
 */
- (nullable NSString *)defaultCachePathForKey:(nullable NSString *)key;

@end

关于SDImageCacheConfig.h文件的内容,关于这个缓存配置的对象,也是暴露在SDWebImageCache.h文件中的一个属性,所以其实我们自己也可以对其进行定制修改

#import <Foundation/Foundation.h>
#import "SDWebImageCompat.h"

@interface SDImageCacheConfig : NSObject

/**
 * Decompressing images that are downloaded and cached can improve performance but can consume lot of memory.
 //解压缩下载的图片和从磁盘中加载的图片会增加性能,但是可能会消耗大量内存
 * Defaults to YES. Set this to NO if you are experiencing a
 crash due to excessive memory consumption.
 默认为YES。如果由于内存消耗过大而导致崩溃,请将此设置为NO。
 */
@property (assign, nonatomic) BOOL shouldDecompressImages;

/**
 * disable iCloud backup [defaults to YES]
 //是否禁止iCloud备份,默认为YES,沙盒中的Documents会备份以及Library/Preference里面的文件
 */
@property (assign, nonatomic) BOOL shouldDisableiCloud;

/**
 * use memory cache [defaults to YES]
 是否启用内存缓存,默认为YES
 */
@property (assign, nonatomic) BOOL shouldCacheImagesInMemory;

/**
 * The reading options while reading cache from disk.
 * Defaults to 0. You can set this to `NSDataReadingMappedIfSafe` to improve performance.
 */
@property (assign, nonatomic) NSDataReadingOptions diskCacheReadingOptions;

/**
 * The writing options while writing cache to disk.
 * Defaults to `NSDataWritingAtomic`. You can set this to `NSDataWritingWithoutOverwriting` to prevent overwriting an existing file.
 */
@property (assign, nonatomic) NSDataWritingOptions diskCacheWritingOptions;

/**
 * The maximum length of time to keep an image in the cache, in seconds.
 磁盘缓存保存的最大时间为一周
 */
@property (assign, nonatomic) NSInteger maxCacheAge;

/**
 * The maximum size of the cache, in bytes.
 磁盘缓存的最大大小 默认为0表示不做限制
 */
@property (assign, nonatomic) NSUInteger maxCacheSize;

@end

下面是SDImageCacheConfig..m文件中的缓存配置中默认的初始化方法其实就一个方法,下面也写了默认的缓存时间为一周

#import "SDImageCacheConfig.h"

static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week

@implementation SDImageCacheConfig

- (instancetype)init {
    if (self = [super init]) {
        _shouldDecompressImages = YES;
        _shouldDisableiCloud = YES;
        _shouldCacheImagesInMemory = YES;
        _diskCacheReadingOptions = 0;
        _diskCacheWritingOptions = NSDataWritingAtomic;
        _maxCacheAge = kDefaultCacheMaxCacheAge;
        _maxCacheSize = 0;
    }
    return self;
}

@end

这里面使用的SDWebImageCache类,这个类继承自NSCache,这里就简单的说下其的用法,这个类有两个属性,其中weakCache相当于就是一个二级弱缓存,而weakCacheLock就是一个保证操作二级弱缓存线程安全。

@property (nonatomic, strong, nonnull) NSMapTable<KeyType, ObjectType> *weakCache; // strong-weak cache
@property (nonatomic, strong, nonnull) dispatch_semaphore_t weakCacheLock; // a lock to keep the access to `weakCache` thread-safe

在init方法中创建二级缓存,并且注册收到内存缓存的通知,使用二级缓存的好处其实就是在收到内存警告的时候,当cache被清空的时候,但是图片的实例还可能在imageView中,所以这个时候我们有二级缓存之后,我们可以不用再去磁盘去加载,而是直接从这个缓存中加载

- (instancetype)init {
    self = [super init];
    if (self) {
        // Use a strong-weak maptable storing the secondary cache. Follow the doc that NSCache does not copy keys
        /* This is useful when the memory warning, the cache was purged. However, the image instance can be retained by other 
         instance such as imageViews and alive.*/
        // At this case, we can sync weak cache back and do not need to load from disk cache
        //NSPointerFunctionsStrongMemory强引用key,弱引用value
        self.weakCache = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0];
        self.weakCacheLock = dispatch_semaphore_create(1);
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(didReceiveMemoryWarning:)
                                                     name:UIApplicationDidReceiveMemoryWarningNotification
                                                   object:nil];
    }
    return self;
}

收到内存警告的时候,调用super的removeAllObjects方法,清除图片缓存

- (void)didReceiveMemoryWarning:(NSNotification *)notification {
    // Only remove cache, but keep weak cache
    [super removeAllObjects];
}

在这个类当中还用到了两个宏,其实就是用GCD的信号量来控制执行的线程的并发数

#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
#define UNLOCK(lock) dispatch_semaphore_signal(lock);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值