首页 > 解决方案 > 为什么 diskConfig.cachePathBlock 应该在这里重置为零?

问题描述

我在看源代码Kingfisher。我在以下代码(源代码)中有一个问题:

为什么diskConfig.cachePathBlocknil在 init 方法结束时重置?我想不通。

public convenience init(
        name: String,
        cacheDirectoryURL: URL?,
        diskCachePathClosure: DiskCachePathClosure? = nil) throws
    {
        if name.isEmpty {
            fatalError("[Kingfisher] You should specify a name for the cache. A cache with empty name is not permitted.")
        }

        let totalMemory = ProcessInfo.processInfo.physicalMemory
        let costLimit = totalMemory / 4
        let memoryStorage = MemoryStorage.Backend<Image>(config:
            .init(totalCostLimit: (costLimit > Int.max) ? Int.max : Int(costLimit)))

        var diskConfig = DiskStorage.Config(
            name: name,
            sizeLimit: 0,
            directory: cacheDirectoryURL
        )
        if let closure = diskCachePathClosure {
            diskConfig.cachePathBlock = closure
        }
        let diskStorage = try DiskStorage.Backend<Data>(config: diskConfig)
        diskConfig.cachePathBlock = nil

        self.init(memoryStorage: memoryStorage, diskStorage: diskStorage)
    }

标签: swiftkingfisher

解决方案


不将该属性设置为 nil 会保持对传入闭包的强引用,并可能造成内存泄漏。将其设置为 nil 可以避免这种情况。

假设 nil 分配不存在,这是一个泄漏示例:

class CacheBuilder {
    func createCache() -> ImageCache {
        let cache = try! ImageCache(name: "Cache", cacheDirectoryURL: nil, diskCachePathClosure: self.path)
        return cache
    }

    func path(_ url: URL, _ str: String) -> URL {
        return url
    }

    deinit {
        print("deinit") // is not called when Cache.init is done
    }
}

class Cache {
    let cache: ImageCache

    init() {
        let builder = CacheBuilder()
        self.cache = builder.createCache()
    }
}

推荐阅读