美文网首页工作需要
iOS SDWebImage 七天清理图片机制

iOS SDWebImage 七天清理图片机制

作者: 不忘初心的初 | 来源:发表于2018-02-02 18:16 被阅读0次

    因项目中涉及到大量的图片展示问题,当图片累计过多时缓存到本地的图片会比较占本地内存空间,影响用户体验,为了提高用户体验,经过讨论后决定添加七天自动清理缓存功能。项目的图片展示是使用的 SDWebImage(以下简称 SD) 这个三方,评估了一下修改三方原代码可能产生的一系列问题。决定独立于三方写一个清除图片缓存的机制。
    经过考虑后想到了一条思路。使用 plist 存储相关图片信息,项目启动后开辟线程读取 plist 信息对并对超过七天的图片进行删除。(思路已定进行代码实现)

    1、首先确认用 SD 来加载图片,在不动 SD 代码的基础上外部处理。找到 SD 缓存图片文件的文件夹,经过查找发现缓存图片都被存在沙盒中此路径下:Library/Caches/default/com.hackemist.SDWebImageCache.default,并且通过文件夹内图片的命名看出是通过 MD5 加密得到的。在查看 SD 原代码后进一步确认了命名规范(图片链接进行 MD5 加密)。这样就能准确的找到指定图片的本地缓存位置。

    2、接下来对 SD 加载图片进行简单的封装,这样也符合高可维护性这一特点。创建一个 plist 文件以便于存储图片名称信息。在封装好的方法中,先调用自定义图片添加方法,按照 id 进行账号区分,在每个账号下创建新的字典,存储图片信息规则是:MD5 加密后的图片链接为 key,当前时间的时间戳为 value。按照 id 和 key 取出对应的时间戳 value 值 ,判断 value 是否为空,为空则把图片链接及时间添加到字典下,不为空则不做处理。

    //获取对应的 plist 地址
    + (NSString *)imgPatchStr {
        NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"imgsClear.plist"];
        return path;
    }
    
    //将未添加的图片名称添加到img.plist中(创建异步线程,防止界面卡顿)
    + (void)addImgViewPlist:(NSString *)imgUrl {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            //plist文件地址
            NSString *path = [CYTextTool imgPatchStr];
            //获取到 plist 文件内的内容
            NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
            //判断是否存在对应的 plist 文件
            if (!dictionary) {
                //如果不存在创建一个 dictionary 便于写入
                dictionary = [NSMutableDictionary dictionary];
            }
            //获取账号下的图片字典
            NSMutableDictionary *idDic = dictionary[kSTU_ID];
            
            if (!idDic) {
                //如果不存在则进行创建
                idDic = [NSMutableDictionary dictionary];
                //将账号字典添加到主字典中
                [dictionary setObject:idDic forKey:kSTU_ID];
            }
            //获取图片对应的时间戳
            NSString *idStr = idDic[imgUrl];
            if (idStr.length == 0) {
                //如果时间戳不存在则表明没有存储该图片信息
                [idDic setObject:[CYTextTool currentTimeStr] forKey:imgUrl];
                //将图片信息写入 plist 文件中
                [dictionary writeToFile:path atomically:YES];
            }
        });
    }
    
    //MD5加密 小写32位 用于对图片名称进行加密
    + (NSString *)strWithMD5:(NSString *)str {
        //要进行UTF8的转码
        const char* input = [str UTF8String];
        unsigned char result[CC_MD5_DIGEST_LENGTH];
        CC_MD5(input, (CC_LONG)strlen(input), result);
        
        NSMutableString *digest = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
        for (NSInteger i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
            [digest appendFormat:@"%02x", result[i]];
        }
        return digest;
    }
    

    3、当 app 启动并到首页后,调用图片查询方法。通过遍历的方式找到7天以外的所有图片名称,按照名称删除掉沙盒中对应的图片。当用户手动清空缓存时,对指定 id 的图片字典进行删除。

    //清理过期图片(创建异步线程,防止界面卡顿)
    + (void)clearWithOverduePictures {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            //自定义的 plist 文件,文件路径抽到了文本处理类中
            NSString *path = [CYTextTool imgPatchStr];
            //获取到 plist 文件内的内容
            NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
            //按照对应的 id 找到该账号下的文件(kSTU_ID 获取当前用户 id 的宏)
            NSMutableDictionary *idDic = dictionary[kSTU_ID];
            //获取当前时间的时间戳
            CGFloat timeNow = [[CYTextTool currentTimeStr] floatValue];
            //创建图片数组便于添加需要删除的图片 
            NSMutableArray *imgArray = [NSMutableArray array];
            //判断是否存在该账号的图片信息
            if (idDic) {
                //遍历字典找到每个图片的时间
                for (NSString *key in idDic) {
                    //后去图片时间戳并与当前时间进行对比(时间戳是毫秒值)
                    CGFloat time = [idDic[key] floatValue];
                    if (time < (timeNow - 7 * 24 * 3600 * 1000)) {
                        [imgArray addObject:key];
                    }
                }
            }
            
            if (imgArray.count != 0) {
                //文件操作对象
                NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
                NSString *imgPath = [NSString stringWithFormat:@"%@%@", cachePath, @"/default/com.hackemist.SDWebImageCache.default"];
                //获取当前位置图片数组
                NSArray *filesNameArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:imgPath error:nil];
                //判断图片缓存位置存在图片后再进行操作
                if (filesNameArray && filesNameArray.count != 0) {
                    for (NSString *imgUrl in imgArray) {
                        //删除缓存中的图片,图片名要拼接上图片类型,我们的图片是jpg的
                        [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@.jpg", imgPath, imgUrl] error:nil];
                        //将应该删除的图片从列表中删除
                        [idDic removeObjectForKey:imgUrl];
                    }
                }
            }
            //将新的字典更新到plist中
            [dictionary writeToFile:path atomically:YES];
        });
    }
    
    //删除图片分组(用户手动清理是可用)
    + (void)deleteAllImgPlist {
        NSString *path = [CYTextTool imgPatchStr];
        NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithContentsOfFile:path];
        //将该账号下的图片信息删除
        [dictionary removeObjectForKey:kSTU_ID];
        //更新图片到 plist 中
        [dictionary writeToFile:path atomically:YES];
    }
    
    //获取当前时间的时间戳
    + (NSString *)currentTimeStr {
        NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0];
        NSTimeInterval time = [date timeIntervalSince1970] * 1000;
        NSString *timeString = [NSString stringWithFormat:@"%.0f", time];
        //将时间转化成字符串的形式进行输出
        return timeString;
    }
    
    

    本人写的不好,只为做相关功能的小伙伴提供一点思路。谢谢!

    相关文章

      网友评论

        本文标题:iOS SDWebImage 七天清理图片机制

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