SDWebImage 学习笔记

时序图.png

1、 SDWebImageOptions 枚举值意义

typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
    /**
     * By default, when a URL fail to be downloaded, the URL is blacklisted so the library won't keep trying.
     * 默认情况下,当一个 URL 下载失败,该URL被列入黑名单,将不会继续尝试下载

     * This flag disable this blacklisting.
     * 此标志取消黑名单

     */
    SDWebImageRetryFailed = 1 << 0,
    
    /**
     * By default, image downloads are started during UI interactions, this flags disable this feature,
     * 默认情况下,在 UI 交互时也会启动图像下载,此标记取消这一功能

     * leading to delayed download on UIScrollView deceleration for instance.
     * 会延迟下载,UIScrollView停止滚动之后再继续下载
     * 下载事件监听的运行循环模式是 NSDefaultRunLoopMode
     */
    SDWebImageLowPriority = 1 << 1,
    
    /**
     * This flag disables on-disk caching
     * 禁用磁盘缓存
     */
    SDWebImageCacheMemoryOnly = 1 << 2, // 只进行内存缓存

    /**
     * This flag enables progressive download, the image is displayed progressively during download as a browser would do.
     * 此标记允许渐进式下载,就像浏览器中那样,下载过程中,图像会逐步显示出来

     * By default, the image is only displayed once completely downloaded.
     * 默认情况下,图像只会在下载完后显示

     */
    SDWebImageProgressiveDownload = 1 << 3,

    /**
     * Even if the image is cached, respect the HTTP response cache control, and refresh the image from remote location if needed.
     * 即使图像被缓存,遵守 HTPP 响应的缓存控制,如果需要,从远程刷新图像

     * The disk caching will be handled by NSURLCache instead of SDWebImage leading to slight performance degradation.
     * 磁盘缓存将由 NSURLCache 处理,而不是 SDWebImage,这会对性能有轻微的影响

     * This option helps deal with images changing behind the same request URL, e.g. Facebook graph api profile pics.
     * 此选项有助于处理同一个请求 URL 的图像发生变化

     * If a cached image is refreshed, the completion block is called once with the cached image and again with the final image.
     * 如果缓存的图像被刷新,会调用一次 completion block,并传递最终的图像

     *
     * Use this flag only if you can't make your URLs static with embedded cache busting parameter.
     * 仅在无法使用嵌入式缓存清理参数确定图像 URL 时,使用此标记

     */
    SDWebImageRefreshCached = 1 << 4, // 刷新
    /**
     * In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for
     * 在 iOS 4+,当 App 进入后台后仍然会继续下载图像。这是向系统请求额外的后台时间以保证下载请求完成的

     * extra time in background to let the request finish. If the background task expires the operation will be cancelled.
     * 如果后台任务过期,请求将会被取消

     */
    SDWebImageContinueInBackground = 1 << 5,

    /**
     * Handles cookies stored in NSHTTPCookieStore by setting
     * 通过设置

     * NSMutableURLRequest.HTTPShouldHandleCookies = YES;
     * 处理保存在 NSHTTPCookieStore 中的 cookies

     */
    SDWebImageHandleCookies = 1 << 6,
    /**
     * Enable to allow untrusted SSL certificates.
     * 允许不信任的 SSL 证书

     * Useful for testing purposes. Use with caution in production.
     * 可以出于测试目的使用,在正式产品中慎用

     */
    SDWebImageAllowInvalidSSLCertificates = 1 << 7,
    
    /**
     * By default, images are loaded in the order in which they were queued. This flag moves them to
     * 默认情况下,图像会按照在队列中的顺序被加载,此标记会将它们移动到队列前部立即被加载

     * the front of the queue.
     */
    SDWebImageHighPriority = 1 << 8,
    
    /**
     * By default, placeholder images are loaded while the image is loading. This flag will delay the loading
     * 默认情况下,在加载图像时,占位图像已经会被加载。而此标记会延迟加载占位图像,直到图像已经完成加载

     * of the placeholder image until after the image has finished loading.
     */
    SDWebImageDelayPlaceholder = 1 << 9,
    /**
     * We usually don't call transformDownloadedImage delegate method on animated images,
     * 通常不会在可动画的图像上调用 transformDownloadedImage 代理方法,因为大多数转换代码会破坏动画文件

     * as most transformation code would mangle it.
     * Use this flag to transform them anyway.
     * 使用此标记尝试转换
     */
    SDWebImageTransformAnimatedImage = 1 << 10,// 改变动画图像
    
    /**
     * By default, image is added to the imageView after download. But in some cases, we want to
     * have the hand before setting the image (apply a filter or add it with cross-fade animation for instance)
     * Use this flag if you want to manually set the image in the completion when success
     */
    SDWebImageAvoidAutoSetImage = 1 << 11  // 避免自动设置图像
};

2、清理磁盘

// 清理磁盘
- (void)cleanDisk {
    [self cleanDiskWithCompletionBlock:nil];
}

- (void)cleanDiskWithCompletionBlock:(SDWebImageNoParamsBlock)completionBlock {
    dispatch_async(self.ioQueue, ^{
        // 1. 找磁盘缓存目录
        NSURL *diskCacheURL = [NSURL fileURLWithPath:self.diskCachePath isDirectory:YES];
        /* 2.
         NSURLIsDirectoryKey, 目录key
         NSURLContentModificationDateKey, url指向的内容,最后修改时间的key
         NSURLTotalFileAllocatedSizeKey 文件总大小的key
         */
        NSArray *resourceKeys = @[NSURLIsDirectoryKey, NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey];
       
        // 3.Enumerator(链表的数据结构存在的) 迭代器的设计模式
        // 创建目录文件的枚举器
        /*
         NSDirectoryEnumerationSkipsHiddenFiles  不遍历隐藏文件
         NSDirectoryEnumerationSkipsSubdirectoryDescendants  不要下载到目录中
         NSDirectoryEnumerationSkipsPackageDescendants 不要下到包
         */
        NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtURL:diskCacheURL
                                                   includingPropertiesForKeys:resourceKeys
                                                                      options:NSDirectoryEnumerationSkipsHiddenFiles
                                                                 errorHandler:NULL];
        
        // 4.从现在开始,减去最大时间
        NSDate *expirationDate = [NSDate dateWithTimeIntervalSinceNow:-self.maxCacheAge];
        
        // 5.定义了一个字典
        NSMutableDictionary *cacheFiles = [NSMutableDictionary dictionary];
        // 6.定义了当前缓存的大小
        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.
        // 7. 创建一个可变数组
        NSMutableArray *urlsToDelete = [[NSMutableArray alloc] init];
        
        // 8.拿到具体的URL
        /*
            1.清楚超过过期时间的文件
            2.以大小为基础进行第二轮文件保存
         */
        for (NSURL *fileURL in fileEnumerator) {
            // 9.获取指定的key的信息, 以字典的方式返回
            NSDictionary *resourceValues = [fileURL resourceValuesForKeys:resourceKeys error:NULL];

            // Skip directories.
            // 10. 判断这个目录,有就直接跳过
            if ([resourceValues[NSURLIsDirectoryKey] boolValue]) {
                continue;
            }

            // Remove files that are older than the expiration date;
            // 11.拿到文件的修改日期
            NSDate *modificationDate = resourceValues[NSURLContentModificationDateKey];
            
            // 12.判断是不是最后修改,是最后修改,就添加到数组
            if ([[modificationDate laterDate:expirationDate] isEqualToDate:expirationDate]) {
                [urlsToDelete addObject:fileURL];
                continue;
            }

            // Store a reference to this file and account for its total size.
            // 14.对未过期的文件, 以键值的形式存起来,方便后面重置缓存
            NSNumber *totalAllocatedSize = resourceValues[NSURLTotalFileAllocatedSizeKey];
            currentCacheSize += [totalAllocatedSize unsignedIntegerValue];
            [cacheFiles setObject:resourceValues forKey:fileURL];
        }
        // 15. 直接删除
        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分支
        if (self.maxCacheSize > 0 && currentCacheSize > self.maxCacheSize) {
            // Target half of our maximum cache size for this cleanup pass.
            // 16. 所需的缓存大小一般的时候
            const NSUInteger desiredCacheSize = self.maxCacheSize / 2;

            // Sort the remaining cache files by their last modification time (oldest first).
            // 把上次缓存的文件进行排序, 最早进来的排第一
            /*NSSortConcurrent 并行的方式
             */
            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();
            });
        }
    });
}

有意思的宏

#define dispatch_main_sync_safe(block)\
    if ([NSThread isMainThread]) {\
        block();\
    } else {\
        dispatch_sync(dispatch_get_main_queue(), block);\
    }

//  安全的主线程操作,if判断很正确
#define dispatch_main_async_safe(block)\
    if ([NSThread isMainThread]) {\
        block();\
    } else {\
        dispatch_async(dispatch_get_main_queue(), block);\
    }

你可能感兴趣的:(SDWebImage 学习笔记)