Алеаторный сбой в SwiftUI при загрузке изображения из Интернета или кеша
Я пытаюсь загрузить изображения и сохранить их в кеше, поэтому у меня есть класс для управления всей последовательностью. Это так:
ImageLoader.swift
import SwiftUI
import UIKit
import Combine
class ImageLoaderCache {
static let shared = ImageLoaderCache()
var loaders: NSCache<NSString, ImageLoader> = NSCache()
func loaderFor(path: String?, size: ImageService.Size) -> ImageLoader {
let key = NSString(string: "\(path ?? "missing")#\(size.rawValue)")
if let loader = loaders.object(forKey: key) {
return loader
} else {
let loader = ImageLoader(path: path, size: size)
loaders.setObject(loader, forKey: key)
return loader
}
}
}
final class ImageLoader: ObservableObject {
let path: String?
let size: ImageService.Size
var objectWillChange: AnyPublisher<UIImage?, Never> = Publishers.Sequence<[UIImage?], Never>(sequence: []).eraseToAnyPublisher()
@Published var image: UIImage? = nil
var cancellable: AnyCancellable?
init(path: String?, size: ImageService.Size) {
self.size = size
self.path = path
self.objectWillChange = $image.handleEvents(receiveSubscription: { [weak self] sub in
self?.loadImage()
}, receiveCancel: { [weak self] in
self?.cancellable?.cancel()
}).eraseToAnyPublisher()
}
private func loadImage() {
guard let poster = path, image == nil else {
return
}
cancellable = ImageService.shared.fetchImage(poster: poster, size: size)
.receive(on: DispatchQueue.main)
.assign(to: \ImageLoader.image, on: self)
}
deinit {
cancellable?.cancel()
}
}
Затем из другого места, чтобы вызвать это, это будет примерно так:
В ImagesCarouselView.swift я вызываю класс, который его использует. (Это просто звонок, а не полный файл)
BigMoviePosterImage(imageLoader: ImageLoaderCache.shared.loaderFor(path: poster.file_path, size: .medium))
А BigMoviePosterImage.swift это:
import SwiftUI
struct BigMoviePosterImage : View {
@ObservedObject var imageLoader: ImageLoader
@State var isImageLoaded = false
var body: some View {
ZStack(alignment: .center) {
if self.imageLoader.image != nil {
Image(uiImage: self.imageLoader.image!)
.resizable()
.renderingMode(.original)
.posterStyle(loaded: true, size: .big)
.scaleEffect(self.isImageLoaded ? 1 : 0.6)
//.animation(.spring())
.onAppear{
self.isImageLoaded = true
}
} else {
Rectangle()
.foregroundColor(.gray)
.posterStyle(loaded: false, size: .big)
}
}
}
}
Проблема в том, что при навигации по приложению оно открывает некоторые представления и подробные представления, используя ImageLoaderCache, а при переходе назад иногда я получаю такую ошибку:
Fatal error: Attempted to read an unowned reference but object 0x1073200c0 was already deallocated
Когда я добавляю точку останова исключения, она указывает на методы ImageLoader и ImageLoaderCache, поэтому я зацикливаюсь, не зная, что делать.