pt 26、2021、TIL(Today I Learned)-属性の計算、拡張、キャッシュで処理できない問題TroubleShooting


Truble:キャッシュの問題を処理できません

extension OpenMarketListCollectionViewCell {
    
    // MARK: - configure cell
    
    func configure(itemInformation: [OpenMarketItem], index: Int) {
      let thumbnailDownloadLink = itemInformation[index].thumbnails[0]
      self.itemThumbnail.applyDownloadedImage(link: thumbnailDownloadLink )
    }
}
ネットワーク通信によってロードされた画像を商品リストに適用するために、上記のapplyDownloadedImage()の方法を用いた.
extension UIImageView {
    private var imageLoader: CachedImageLoader {
        return CachedImageLoader(imageDownloader: ImageDownloader(network: Network()))
    }
    
    func applyDownloadedImage(link: String) {
        imageLoader.loadImageWithCache(with: link) { image in
            DispatchQueue.main.async {
                self.image = image
            }
        }
    }
}
この方法は、UIImageViewを拡張し、imageLoaderメソッドによってCachedImageLoderと呼ばれるタイプのモジュールを演算プログラムとして宣言し、loadImageWithCache()メソッドによってイメージをロードする.
final class CachedImageLoader {
    private let cache = ImageCache<NSString, UIImage>()
    private let imageDownloader: ImageDownloadable
    
    
    init(imageDownloader: ImageDownloadable) {
        self.imageDownloader = imageDownloader
    }
    
    func loadImageWithCache(with link: String, completion: @escaping (UIImage) ->()) {
        let nsText = link as NSString
        
        if let cachedImage = cache[nsText] {
            return completion(cachedImage)
        }

        imageDownloader.downloadImage(url: link.createURL()) { result in
            switch result {
            case .failure(let error):
                NSLog(error.localizedDescription)
            case .success(let image):
                self.cache.insert(image, forkey: nsText)
                return completion(image)
            }
        }
    }
}
CachedImageLoaderのタイプは次のとおりです.
内部はcacheおよびimageDownloaderであり、imageDownloaderによって受信された初期イメージデータはクラス内部cacheに格納され、UIImgeに戻り、その後同じイメージが受信された場合、cache内部でイメージが存在するかどうかをチェックし、キャッシュに存在する場合、受信されたイメージ適用される論理.
これは問題のない構造に見えますが、プロジェクトを実行すると、イメージがキャッシュできないことがわかります.何か問題がありますか.

TroubleShooting:計算プログラムのプログラム初期化の問題


こんな渋滞しているところがあったら、もちろん先に調整しなければなりませんよね?
真剣にデバッグしている間に変なところを見つけました.CachedImageLoaderオブジェクトのself.cache.insert(image, forKey: nsText)このセクションではbreakpointを撮影し、imageCacheを表示します.次のログが表示されます.
<ImageCache<NSString, UIImage>: 0x60000330d580>
<ImageCache<NSString, UIImage>: 0x60000330d940>
<ImageCache<NSString, UIImage>: 0x60000330da80>
ブーブー!なんてことだ.INSERTの度にImageCacheのアドレスが違います
なぜかよく考えてみると...UIImageLoaderはUIImageViewの拡張から計算プログラムでロードされます.
private var imageLoader: CachedImageLoader {
        return CachedImageLoader(imageDownloader: ImageDownloader(network: Network()))
    }
これにより、新しいimageLoaderインスタンスが作成されるたびに、imageLoaderのキャッシュに画像が保存されます.(私はバカ…)
したがって、各セルでself.itemThumbnail.applyDownloadedImage(link: thumbnailDownloadLink )操作を行うたびに、imageLoaderインスタンスのimageCacheに格納される――、――

トラブルシューティング

UIImageViewの拡張では、ImageLoaderを使用してキャッシュを格納し、ViewControllerのImageLoaderを使用して画像キャッシュを格納し、CacheManagerクラスを作成しました.このクラスは、このときに単一のトーンモードを使用するのに最適なので、キャッシュを共通のストレージとして使用することができます.
import UIKit

final class CacheManager {
    let cache = ImageCache<NSString, UIImage>(totalCostLimit: 500 * 1024 * 1024)
    
    static let shared = CacheManager()
    private init() { }
}
CachedImageLoaderの内部を変更しました.
func loadImageWithCache(with link: String, completion: @escaping (UIImage) ->()) {
        let nsText = link as NSString
        
        if let cachedImage = CacheManager.shared.cache[nsText] {
            return completion(cachedImage)
        }

        imageDownloader.downloadImage(url: link.createURL()) { result in
            switch result {
            case .failure(let error):
                NSLog(error.localizedDescription)
            case .success(let image):
                CacheManager.shared.cache.insert(image, forkey: nsText)
                return completion(image)
            }
        }
    }
これにより、イメージが正常にキャッシュに格納されることを確認できます.

の最後の部分


今日また1つの拡張と演算プログラムを理解して、私はとても喜んでいます!これからは二度と今日のようなミスを犯すことはありません!!