欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS学习笔记-127.SDWebImage3——缓存的清除和操作的取消

程序员文章站 2022-07-03 21:10:47
SDWebImage3——缓存的清除和操作的取消 一、清除缓存和操作最方便放在那里 当我们的app需要在多个控制器上显示图片的时候,如果发生内存警告,我...

SDWebImage3——缓存的清除和操作的取消

一、清除缓存和操作最方便放在那里

当我们的app需要在多个控制器上显示图片的时候,如果发生内存警告,我们想自己来清除缓存。那么我应该放在什么地方呢?

可以放在控制器中,不过多个控制器都用来了,需要每个地方都来写,感觉有点淡淡的忧伤

放到 AppDelegate 中,这样我们只需要写一次就行啦。


二、缓存清除方法

清除缓存的方法,我们可以通过 SDWebImageManager 的单例中的 imageCache对象的方法来调用。如

[[SDWebImageManager sharedManager].imageCache clearMemory];

2.1 clearMemory清除内存

清除内存缓存,我们可以使用如下的方法

[[SDWebImageManager sharedManager].imageCache clearMemory];

那么它到底干了一些什么事情呢,我们去看看

这个方法在 SDImageCache中,如下

//清除内存缓存
- (void)clearMemory {
    //把所有的内存缓存都删除
    [self.memCache removeAllObjects];
}

简单粗暴,删除所有内存缓存


2.2 clearDisk清除磁盘

清除内存缓存,我们可以使用如下的方法

[[SDWebImageManager sharedManager].imageCache clearMemory];

那么它到底干了一些什么事情呢,我们去看看

这个方法在 SDImageCache中,如下

//清除磁盘缓存
- (void)clearDisk {
    [self clearDiskOnCompletion:nil];
}

//清除磁盘缓存(简单粗暴)
- (void)clearDiskOnCompletion:(SDWebImageNoParamsBlock)completion
{
    //开子线程异步处理 清理磁盘缓存的操作
    dispatch_async(self.ioQueue, ^{
        //删除缓存路径
        [_fileManager removeItemAtPath:self.diskCachePath error:nil];
        //重新创建缓存路径
        [_fileManager createDirectoryAtPath:self.diskCachePath
                withIntermediateDirectories:YES
                                 attributes:nil
                                      error:NULL];

        if (completion) {
            //在主线程中处理completion回调
            dispatch_async(dispatch_get_main_queue(), ^{
                completion();
            });
        }
    });
}

同样这个清除磁盘的方式也是一样,直接删除缓存文件夹,然后在创建一个空的文件夹,完成这些操作以后,去主线中处理 completion回调。


2.2 cleanDisk清除磁盘

这个方法清除磁盘,主要从两个方面出发,

第一、文件过期那么清除,

第二、计算当前缓存的大小,和设置的最大缓存数量比较,如果超出那么会继续删除(按照文件了创建的先后顺序)

这个方法在 SDImageCache中,如下

//清除过期的磁盘缓存
- (void)cleanDisk {
    [self cleanDiskWithCompletionBlock:nil];
}

//清除过期的磁盘缓存
- (void)cleanDiskWithCompletionBlock:(SDWebImageNoParamsBlock)completionBlock {
    dispatch_async(self.ioQueue, ^{
        NSURL *diskCacheURL = [NSURL fileURLWithPath:self.diskCachePath isDirectory:YES];
        NSArray *resourceKeys = @[NSURLIsDirectoryKey, NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey];

        // This enumerator prefetches useful properties for our cache files.
        NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtURL:diskCacheURL
                                                   includingPropertiesForKeys:resourceKeys
                                                                      options:NSDirectoryEnumerationSkipsHiddenFiles
                                                                 errorHandler:NULL];

        // 计算过期日期
        NSDate *expirationDate = [NSDate dateWithTimeIntervalSinceNow:-self.maxCacheAge];
        NSMutableDictionary *cacheFiles = [NSMutableDictionary dictionary];
        NSUInteger currentCacheSize = 0;

        // Enumerate all of the files in the cache directory.  This loop has two purposes:
        //
        //  1. Removing files that are older than the expiration date.
        //  2. Storing file attributes for the size-based cleanup pass.
        // 遍历缓存路径中的所有文件,此循环要实现两个目的
        //  1. 删除早于过期日期的文件
        //  2. 保存文件属性以计算磁盘缓存占用空间
        NSMutableArray *urlsToDelete = [[NSMutableArray alloc] init];
        for (NSURL *fileURL in fileEnumerator) {
            NSDictionary *resourceValues = [fileURL resourceValuesForKeys:resourceKeys error:NULL];

            // Skip directories.
            // 跳过目录
            if ([resourceValues[NSURLIsDirectoryKey] boolValue]) {
                continue;
            }

            // Remove files that are older than the expiration date;
            // 记录要删除的过期文件

            NSDate *modificationDate = resourceValues[NSURLContentModificationDateKey];
            if ([[modificationDate laterDate:expirationDate] isEqualToDate:expirationDate]) {
                [urlsToDelete addObject:fileURL];
                continue;
            }

            // Store a reference to this file and account for its total size.
            //保存文件引用,以计算总大小
            NSNumber *totalAllocatedSize = resourceValues[NSURLTotalFileAllocatedSizeKey];
            currentCacheSize += [totalAllocatedSize unsignedIntegerValue];
            [cacheFiles setObject:resourceValues forKey:fileURL];
        }

        // 删除过期的文件
        for (NSURL *fileURL in urlsToDelete) {
            [_fileManager removeItemAtURL:fileURL error:nil];
        }

        // If our remaining disk cache exceeds a configured maximum size, perform a second
        // size-based cleanup pass.  We delete the oldest files first.
        //如果剩余磁盘缓存空间超出最大限额,再次执行清理操作,删除最早的文件
        if (self.maxCacheSize > 0 && currentCacheSize > self.maxCacheSize) {
            // Target half of our maximum cache size for this cleanup pass.
            const NSUInteger desiredCacheSize = self.maxCacheSize / 2;

            // Sort the remaining cache files by their last modification time (oldest first).
            NSArray *sortedFiles = [cacheFiles keysSortedByValueWithOptions:NSSortConcurrent
                                                            usingComparator:^NSComparisonResult(id obj1, id obj2) {
                                                                return [obj1[NSURLContentModificationDateKey] compare:obj2[NSURLContentModificationDateKey]];
                                                            }];

            // Delete files until we fall below our desired cache size.
            // 循环依次删除文件,直到低于期望的缓存限额
            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;
                    }
                }
            }
        }
        //在主线程中处理完成回调
        if (completionBlock) {
            dispatch_async(dispatch_get_main_queue(), ^{
                completionBlock();
            });
        }
    });
}

2.4 最大缓存时间

上面我们涉及到了最大缓存时间,那么它的值是多少呢?

SDImageCache 的下面方法中定义了这个默认值


//使用指定的命名空间实例化一个新的缓存存储和目录
- (id)initWithNamespace:(NSString *)ns diskCacheDirectory:(NSString *)directory {
......
//初始化默认的最大缓存时间 == 1周
_maxCacheAge = kDefaultCacheMaxCacheAge;
......
}

我们再来看看 kDefaultCacheMaxCacheAge


//默认的最大缓存时间为1周
static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week

所以默认最大缓存时间是一个周。

### 2.5 最大缓存大小

上面我们知道,cleanDisk 的时候,除了时间,还有缓存的大小也是判断的依据,那么我们来看看,最大的缓存大小。


/**
* The maximum size of the cache, in bytes.
*
* 缓存图像总大小,以字节为单位,默认数值为0,表示不作限制
*/
@property (assign, nonatomic) NSUInteger maxCacheSize;


三、取消操作

//取消当前的所有操作
[[SDWebImageManager sharedManager] cancelAll];

四、示例代码

//
//  AppDelegate.m
//  03_UIview87_SDWebImage
//
//  Created by 杞文明 on 17/9/7.
//  Copyright ? 2017年 杞文明. All rights reserved.
//

#import "AppDelegate.h"
#import "SDWebImageManager.h"
@interface AppDelegate ()

@end

@implementation AppDelegate

-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application{
    //1.清空缓存
    //clear:直接删除缓存目录下面的文件,然后重新创建空的缓存文件
    //clean:清除过期缓存,计算当前缓存的大小,和设置的最大缓存数量比较,如果超出那么会继续删除(按照文件了创建的先后顺序)
    //过期时间:7天
    [[SDWebImageManager sharedManager].imageCache cleanDisk];
//    [[SDWebImageManager sharedManager].imageCache clearMemory];

    //2.取消当前的所有操作
    [[SDWebImageManager sharedManager] cancelAll];
}

@end