我的缓存系统导致内存泄漏

时间:2016-09-12 10:42:05

标签: ios swift caching memory-leaks

我有一个我创建的数据结构,它使用Dictionary和Queue的组合来缓存项目。想法是将项目添加到"缓存"一旦达到极限,缓存中最旧的项目将被删除:

struct Cache<A: Hashable, B> {
    fileprivate var theCache = [A:B]()
    fileprivate var keyQueue = Queue<A>()
    fileprivate var maxItems: Int!

    init(maxItems: Int) {
        self.maxItems = maxItems
    }

    subscript(key : A?) -> B? {
        get {
            if key != nil {
                return theCache[key!]
            }
            return nil
        }
        set(newValue) {
            // If value being added to cache, check that the max no. of items isn't exceeded.
            // If it is then remove the first item of the cache queue and add value to queue.
            if key != nil {
                if (theCache.count + 1 > maxItems) {
                    removeFirstItem()
                }
                addValue(key!, value: newValue)
            }
        }
    }

    /**
     Tells us how many items there are in the cache

     - returns: The count of the cache
     */
    var count: Int {
        return theCache.count
    }

    mutating func clear() {
        theCache.removeAll()
        for _ in 0..<keyQueue.count {
            _ = keyQueue.dequeue()
        }
    }

    fileprivate mutating func addValue(_ key: A, value: B?) {
        theCache[key] = value // Memory leak 2
        keyQueue.enqueue(key)
    }

    fileprivate mutating func removeFirstItem() {
        let firstItemKey = keyQueue.dequeue()
        if firstItemKey != nil {
            theCache.removeValue(forKey: firstItemKey!)
        }
    }
}

我使用此功能在UIImages中缓存UICollectionView,并从我的model类中强烈引用此缓存。

在我的cellForItemAt方法中,我有以下代码来检查缓存的图像。如果有缓存图像,则会将其添加到UICollectionCell,否则会将其下载,将其添加到缓存中,然后将其添加到UICollectionCell

if let cellImage = model.imageCache[urlString] {
    cell.imageView.image = cellImage
}
else {
    model.downloadImage(
        urlString,
        completion: { [weak self] (error, image) -> () in
            if let strongSelf = self {
                if error == nil {
                    // Store the image in to our cache
                    strongSelf.model.imageCache[urlString] = image
                    // Update the cell with our image
                   if let cellToUpdate = collectionView.cellForItem(at: indexPath) as? MyCollectionCell {
                        cellToUpdate.imageView.image = image
                    }
                }
                else {
                    print("Error downloading image: \(error!.localizedDescription)")
                }
            }
        }
    )
}

然而,根据Xcode 8,整个过程导致UIImages的内存泄漏。任何人都可以帮我解决内存泄漏的问题以及如何防止内存泄漏吗?

修改

这是我的downloadImage功能。我还添加了内存泄漏1&#34;和&#34;内存泄漏2&#34;作为我的代码旁边的注释,显示内存泄漏的回溯xcode告诉我:

Alamofire.request(urlString, method: .get)
         .authenticate(usingCredential: credentials!)
         .validate()
         .downloadProgress { bytesRead, totalBytesRead, totalBytesExpectedToBeRead  in
             DispatchQueue.main.async {
                 progress?(Float(totalBytesRead)/Float(totalBytesExpectedToBeRead))
             }
         }
         .responseData { response in
             // Convert the downloaded data in to a UIImage object
             var image: UIImage?
             if response.result.error == nil {
                 image = UIImage(data: response.data!) // Memory leak 1
             }
             completion(response.result.error, image)
         }

0 个答案:

没有答案