读读SDImageCache

Cahce一般主要有以下点需要掌握:

  • cache存在哪里
  • cache如何存
  • cache操作
  • cache管理

1.存在哪里?

从默认属性和以上两个函数可以看出,SD默认缓存图片到内存,如果显示指定toDisk,则同时缓存图片到文件中。SD使用了系统提供的NSCache作为缓存容器,NSCache一个优势就是可以依据当前内存使用情况动态调整缓存(当系统内存出现告警时,自动释放一些缓存)。在使用NSCache时,可以传递缓存对象大小用来标记。SD在这一点也做出相应的处理。具体如下

1)对NSCache类扩展,监听系统内存告警通知。当收到系统内存告警通知时,自动释放全部Cache对象。
2)NSCache缓存对象时,主动计算该对象大小。


2.如何存?

1)通过串行队列执行缓存操作,保证了FIFO操作。
2)缓存前对原始数据进行PNG转换,保证了缓存最大化。
3)未加入图片压缩处理。


3.cache操作

1. 缓存图片
  • (void)storeImage:(UIImage *)image forKey:(NSString *)key;
  • (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk;
2. 获取缓存图片
  • (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock;
  • (UIImage *)imageFromMemoryCacheForKey:(NSString *)key;
  • (UIImage *)imageFromDiskCacheForKey:(NSString *)key;
3. 删除缓存图片
  • (void)removeImageForKey:(NSString *)key;
  • (void)removeImageForKey:(NSString *)key withCompletion:(SDWebImageNoParamsBlock)completion;
  • (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk;
  • (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(SDWebImageNoParamsBlock)completion;
4. 清空缓存
  • (void)clearMemory;
  • (void)clearDiskOnCompletion:(SDWebImageNoParamsBlock)completion;
  • (void)clearDisk;
  • (void)cleanDiskWithCompletionBlock:(SDWebImageNoParamsBlock)completionBlock;
  • (void)cleanDisk;

4.cache管理

1. 缓存有效期处理

SD默认的缓存时间是一周。在清除过期缓存图片时,首先遍历当前缓存目录下面的所有文件,删除过期文件,再重置缓存大小。

遍历缓存目录使用下面函数:

NSArray *resourceKeys = @[NSURLIsDirectoryKey, NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey];

NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtURL:diskCacheURL
                                               includingPropertiesForKeys:resourceKeys                                                              options:NSDirectoryEnumerationSkipsHiddenFiles
                                                             errorHandler:NULL];

归档过期缓存:

    for (NSURL *fileURL in fileEnumerator) 
    {
        ......
        // 根据文件路径最后修改时间来获取内容
        NSDate *modificationDate = resourceValues[NSURLContentModificationDateKey];
    // 判断是否过缓存期
        if ([[modificationDate laterDate:expirationDate] isEqualToDate:expirationDate])         {
            [urlsToDelete addObject:fileURL];
            continue;
        }

        // 这里同时对未过期的文件根据文件大小进行归档,便以后续重置缓存.
        NSNumber *totalAllocatedSize = resourceValues[NSURLTotalFileAllocatedSizeKey];
        currentCacheSize += [totalAllocatedSize unsignedIntegerValue];
        [cacheFiles setObject:resourceValues forKey:fileURL];
    }

删除过期缓存:

    for (NSURL *fileURL in urlsToDelete) {
        [_fileManager removeItemAtURL:fileURL error:nil];
    }       

重置缓存大小:

    // 依据文件修改时间,对未过期的文件进行升序排序.
    NSArray *sortedFiles = [cacheFiles keysSortedByValueWithOptions:NSSortConcurrent
                                                        usingComparator:^NSComparisonResult(id obj1, id obj2) {
                                                            return [obj1[NSURLContentModificationDateKey] compare:obj2[NSURLContentModificationDateKey]];
                                                        }];

        // 根据设定的缓存大小,对当前缓存进行调整,删除那些快过期的文件,使当前总的文件大小小与设定的缓存大小。
        for (NSURL *fileURL in sortedFiles) {
            if ([_fileManager removeItemAtURL:fileURL error:nil]) {
                NSDictionary *resourceValues = cacheFiles[fileURL];
                NSNumber *totalAllocatedSize = resourceValues[NSURLTotalFileAllocatedSizeKey];
                currentCacheSize -= [totalAllocatedSize unsignedIntegerValue];

                if (currentCacheSize < desiredCacheSize) {
                    break;
                }
            }
        }
2. 系统通知处理

当收到系统内存告警通知时,对内存缓存进行处理。

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(clearMemory)
                                name:UIApplicationDidReceiveMemoryWarningNotification
                                               object:nil];

当进程终止时,对缓存文件进行处理。

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(cleanDisk)
                                                 name:UIApplicationWillTerminateNotification
                                               object:nil];

当进入后台运行时,对缓存文件进行处理。

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(backgroundCleanDisk)
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];

SD的缓存其实没有太复杂的东西,细节处理还是比较好。NSCache确实是个好东西,不过被NSDictionary给压住了。哈哈。

你可能感兴趣的:(读读SDImageCache)