Алеаторный сбой в 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, поэтому я зацикливаюсь, не зная, что делать.

0 ответов

Другие вопросы по тегам