这是我参与更文挑战的第11天,活动详情查看: 更文挑战

Kingfisher 是喵神维护的纯 Swift 库,用于从 Web 下载和缓存图像,类似于 SDWebImage缓存是什么意思。目前已经有 18.5K 的 Star。

下面是阅读源码中的收货。

autoreleasepooswift是什么l 的使用

Swift 在内存管理上使用的是自动引用计数 (ARC) 的一套方法,在平时的编码过程中很少需要考虑内容释放的问题。以此同缓存视频怎样转入相册时也很容易忽略 autoreleasepool 的用法。

在创建内存较大的对象,或者在循环中需要不断的创建对象时,可以考虑使用 autoreleasepool 及时的清理内存对象。

关于 autoreleasepool 可以查看喵神的文章@AUTORELEASEPOOL。

在 Kingfisher 中在将 UIImage 转成 Data 时,使用到了 autorele源码asepool,代码如下:

 public func data(format: ImageFormat, compressionQuality: CGFloat = 1.0) -> Data? {
    return autoreleasepool { () -> Data? in
        let data: Data?
        switch format {
        case .PNG: data = pngRepresentation()
        case .JPEG: data = jpegRepresentation(compressionQuality: compressionQuality)
        case .GIF: data = gifRepresentation()
        case .unknown: data = normalized.kf.pngRepresentation()
        }
        return data
    }
}

namespace(命名空间)的使用

在使用第三方库的时候,经常会见到 namespace(命名空间),比如: S缓存的视频在哪napKit 的 snpRxSswifterwiftrx。同样 Kingfisher 使用了 kf 作为命名swift翻译空间。

使用 namespace 可以避免与其它框架 API 同名,可以通过Swift如何创建命名空间查看具体使用。

除了框架需要考虑使用的 nameswift是什么space,在框架内部的一个单独的模块也可以考虑使用 namespace

在 Kingfisher 中,MemoryStorage 表示内存存储的名称空间,DiskStorage 表示磁盘存储的命名空间。下面分析一下 DiskStorage 的设计。

public enum DiskStorage {
    public class Backend<T: DataTransformable> {
    }
}
extension DiskStorage {
    public struct Config {
    }
}
extension DiskStorage {
    struct Creation {
    }
}

负责充当命名空间的 DiskStorage 的类型为 enum,其中主要负责存储的类 Backend 定义在Swift DiskStorage 中,并且放在了代码文件的缓存视频合并app顶部,其他相关的类放在了 DiskStorage 的扩展中。

通知这种模块的命名空间,有两个功能

  • 可以有效的缩短了类名、结构名,而且更加的清晰。DiskStorage.Config 总要好过 DiskStorageConfig
  • 将相关的类定义在了一起,代码结构非常清晰。

文件的存储

为了频繁的从网络上请求数据,下载下来的图片资源必定会缓存文件夹名称存储在本地。那怎么保存、获取文件资源的最后一次访问时间和过期时间呢?

首先想到的可能是:用一个专门的文件来保存资源和对应的时间swift代码。Kingfisher 的策源码网站略是使用文件的属性来跟踪文件的最后访问时间和过期时间的。源码

存储文件时间

在保存完一个资源资源之后,通过 fileManagersetAttributes(_ attributes:ofItemAtPath源码精灵永久兑换码 path:) 方法设置资源的属性。如下:

let now = Date()
let attributes: [FileAttributeKey : Any] = [
    // The last access date.
    .creationDate: now.fileAttributeDate,
    // The estimated expiration date.
    .modificationDate: expiration.estimatedExpirationSinceNow.fileAttributeDate //
]
do {
    try config.fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path)
} catch {
    try? config.fileManager.removeItem(at: fileURL)
    throw KingfisherError.cacheError(
        reason: .cannotSetCacheFileAttribute(
            filePath: fileURL.path,
            attributes: attributes,
            error: error
        )
    )
}

使用 FileAttributeKey 的 creationDate 表示最后访问时间,modificationDate 表示过期时间。当然,creationDate 和 modificationDate 的原本的含义应该是用来描述文件的创建时间,修RxSwift改时间。

获取文件时间

获取文件资源的时间使用的是 URL 的 resourceValues(forKeswiftlyys keys:) 方法。如下源码中的图片

let resourceKeys: Set<URLResourceKey> = [.contentModificationDateKey, .creationDateKey]
let meta = try fileURL.resourceValues(forKeys: resourceKeys)

使用了 URLswift翻译ResourceKeycreationDateKey 表示最后访问时间, contentModificationDateKey 表示过期时间。之后就可以通过 meta 的属性进行访问了。

meta.creationDate
meta.contentModificationDate ->

在清理过期文件时,除了获取 creationDateKeyfileSizeKey(表示文件大小),还需要获取 isDirectoryKey,用来需要判断 URL 是否为文件夹路径,避免之后再判断 isDirectory

let propertyKeys: [URLResourceKey] = [
    .isDirectoryKey,
    .creationDateKey, 
    .fileSizeKey
]

注意:保存日期时是通过 FileMswift是什么意思啊anager 设置文件的 F缓存视频怎样转入相册ileAttributeKey 对应的值,获取时是通过 URL 的 resourceValues 方法获取 URLResourceKey 对应的值。