Swiftui 使用Combine framwork时在何处设置图像缓存

Swiftui 使用Combine framwork时在何处设置图像缓存,swiftui,combine,image-caching,Swiftui,Combine,Image Caching,学习如何在YouTube中使用本机NSCache缓存图像 下面是运行良好的示例代码。在从URLSession.shared.dataTask返回数据后,我可以看到它在getimagefromsresponse方法中将图像设置到缓存中。这是使用@escaping完成处理程序的老方法 import Foundation import SwiftUI class UrlImageModel: ObservableObject { @Published var image: UIImage?

学习如何在YouTube中使用本机NSCache缓存图像

下面是运行良好的示例代码。在从
URLSession.shared.dataTask
返回数据后,我可以看到它在
getimagefromsresponse
方法中将图像设置到缓存中。这是使用@escaping完成处理程序的老方法

import Foundation
import SwiftUI

class UrlImageModel: ObservableObject {
    @Published var image: UIImage?
    var urlString: String?
    var imageCache = ImageCache.getImageCache()

    init(urlString: String?) {
        self.urlString = urlString
        loadImage()
    }

    func loadImage() {
        if loadImageFromCache() {
            print("Cache hit")
            return
        }

        print("Cache miss, loading from url")
        loadImageFromUrl()
    }

    func loadImageFromCache() -> Bool {
        guard let urlString = urlString else {
            return false
        }

        guard let cacheImage = imageCache.get(forKey: urlString) else {
            return false
        }

        image = cacheImage
        return true
    }

    func loadImageFromUrl() {
        guard let urlString = urlString else {
            return
        }

        let url = URL(string: urlString)!
        let task = URLSession.shared.dataTask(with: url, completionHandler: getImageFromResponse(data:response:error:))
        task.resume()
    }


    func getImageFromResponse(data: Data?, response: URLResponse?, error: Error?) {
        guard error == nil else {
            print("Error: \(error!)")
            return
        }
        guard let data = data else {
            print("No data found")
            return
        }

        DispatchQueue.main.async {
            guard let loadedImage = UIImage(data: data) else {
                return
            }

            self.imageCache.set(forKey: self.urlString!, image: loadedImage)
            self.image = loadedImage
        }
    }
}

class ImageCache {
    var cache = NSCache<NSString, UIImage>()

    func get(forKey: String) -> UIImage? {
        return cache.object(forKey: NSString(string: forKey))
    }

    func set(forKey: String, image: UIImage) {
        cache.setObject(image, forKey: NSString(string: forKey))
    }
}

extension ImageCache {
    private static var imageCache = ImageCache()
    static func getImageCache() -> ImageCache {
        return imageCache
    }
}
///更新,我找到了怎么做。添加Combine
handleEvents
方法,并在receiveOutput闭包中设置图像缓存,以解决此问题。顺便说一句,有更多的参数,处理上游出版商和下游接收器。对我来说,这需要更多的实践才能在Combine中使用这种新的网络方式

修复了代码,我还在图像缓存部分添加了一个下标

import Foundation
import SwiftUI
import Combine

class UrlImageModel: ObservableObject {
    @Published var image: UIImage?
    private var url: URL?
    private var cancellable: AnyCancellable?
    private var imageCache = ImageCache.getImageCache()

    init(url: URL?) {
        self.url = url
        loadImage()
    }

    func loadImage() {
        if loadImageFromCache() {
            print("Cache hit")
            return
        }

        print("Cache missing, loading from url")
        loadImageFromUrl()
    }

    func loadImageFromCache() -> Bool {
        guard let url = url else {
            return false
        }

        guard let cacheImage = imageCache[url] else {
            return false
        }

        image = cacheImage
        return true
    }

    func loadImageFromUrl() {
        guard let url = url else {
            return
        }

        cancellable = URLSession.shared.dataTaskPublisher(for: url)
            .map { UIImage(data: $0.data) }
            .replaceError(with: nil)
            // set image into cache!
            .handleEvents(receiveOutput: { [unowned self] image in
                guard let image = image else {return}
                self.imageCache[url] = image
            })
            .receive(on: DispatchQueue.main)
            .assign(to: \.image, on: self)
    }
}

class ImageCache {
    var cache = NSCache<NSURL, UIImage>()

    subscript(_ key: URL) -> UIImage? {
        get { cache.object(forKey: key as NSURL) }
        set { newValue == nil ? cache.removeObject(forKey: key as NSURL) : cache.setObject(newValue!, forKey: key as NSURL) }
    }
}

extension ImageCache {
    private static var imageCache = ImageCache()

    static func getImageCache() -> ImageCache {
        return imageCache
    }
}
<代码>导入基础 导入快捷键 进口联合收割机 类UrlImageModel:ObservableObject{ @已发布的var图像:UIImage? 私有变量url:url? 私有var可取消:任何可取消? private var imageCache=imageCache.getImageCache() 初始化(url:url?){ self.url=url loadImage() } func loadImage(){ 如果loadImageFromCache(){ 打印(“缓存命中”) 返回 } 打印(“缓存丢失,从url加载”) loadImageFromUrl() } func loadImageFromCache()->Bool{ guard let url=url else{ 返回错误 } guard let cacheImage=imageCache[url]else{ 返回错误 } image=cacheImage 返回真值 } func loadImageFromUrl(){ guard let url=url else{ 返回 } Cancelable=URLSession.shared.dataTaskPublisher(for:url) .map{UIImage(数据:$0.data)} .replaceError(带:nil) //将图像设置为缓存! .handleEvents(接收输出:{[unowned self]图像在 guard let image=image else{return} self.imageCache[url]=图像 }) .receive(在:DispatchQueue.main上) .assign(到:\.image,在:self上) } } 类ImageCache{ var cache=NSCache() 下标(ukey:URL)->UIImage{ 获取{cache.object(forKey:key作为NSURL)} set{newValue==nil?cache.removeObject(forKey:key作为NSURL):cache.setObject(newValue!,forKey:key作为NSURL)} } } 扩展映像缓存{ 私有静态变量imageCache=imageCache() 静态函数getImageCache()->ImageCache{ 返回图像缓存 } }
import Foundation
import SwiftUI
import Combine

class UrlImageModel: ObservableObject {
    @Published var image: UIImage?
    private var url: URL?
    private var cancellable: AnyCancellable?
    private var imageCache = ImageCache.getImageCache()

    init(url: URL?) {
        self.url = url
        loadImage()
    }

    func loadImage() {
        if loadImageFromCache() {
            print("Cache hit")
            return
        }

        print("Cache missing, loading from url")
        loadImageFromUrl()
    }

    func loadImageFromCache() -> Bool {
        guard let url = url else {
            return false
        }

        guard let cacheImage = imageCache[url] else {
            return false
        }

        image = cacheImage
        return true
    }

    func loadImageFromUrl() {
        guard let url = url else {
            return
        }

        cancellable = URLSession.shared.dataTaskPublisher(for: url)
            .map { UIImage(data: $0.data) }
            .replaceError(with: nil)
            // set image into cache!
            .handleEvents(receiveOutput: { [unowned self] image in
                guard let image = image else {return}
                self.imageCache[url] = image
            })
            .receive(on: DispatchQueue.main)
            .assign(to: \.image, on: self)
    }
}

class ImageCache {
    var cache = NSCache<NSURL, UIImage>()

    subscript(_ key: URL) -> UIImage? {
        get { cache.object(forKey: key as NSURL) }
        set { newValue == nil ? cache.removeObject(forKey: key as NSURL) : cache.setObject(newValue!, forKey: key as NSURL) }
    }
}

extension ImageCache {
    private static var imageCache = ImageCache()

    static func getImageCache() -> ImageCache {
        return imageCache
    }
}