Попытка прочитать неопознанную ссылку, но объект уже был освобожден Swift 5 - PullRequest
2 голосов
/ 15 февраля 2020

У меня проблема с освобождением переменной: кеш

Это из учебника Кэш многократного использования изображений в Swift

enter image description here

Ошибка:

Неустранимая ошибка: Попытка прочитать неизвестную ссылку, но объект 0x280208080 уже освобожден Неустранимая ошибка: Попытка прочитать неизвестную ссылку, но объект 0x280208080 был уже освобожден

Код:

final class ImageLoader {

private let cache = ImageCache()

func loadImage(from url: URL) -> AnyPublisher<UIImage?, Never> {
    if let image = cache[url] {
        return Just(image).eraseToAnyPublisher()
    }
    return URLSession.shared.dataTaskPublisher(for: url)
        .map { UIImage(data: $0.data) }
        .catch { error in return Just(nil) }
        .handleEvents(receiveOutput: {[unowned self] image in
            guard let image = image else { return }
            self.cache[url] = image
        })
        .subscribe(on: DispatchQueue.global(qos: .background))
        .receive(on: RunLoop.main)
        .eraseToAnyPublisher()
}
}

1 Ответ

1 голос
/ 11 марта 2020

Эта ошибка имеет довольно простое объяснение:

к тому времени, когда URLSession завершает свою работу, экземпляр ImageLoader не существует, потому что никто не хранит ссылку на него. Это может произойти, когда вы просто создаете этот экземпляр в переменной области видимости функции. (Может быть, в какой-то функции, например viewDidLoad). Этот cra sh полезен, так как говорит, что загрузчик используется неправильно. В случае использования слабого я или захвата всего экземпляра, cra sh не произойдет, но у вас будет много ImageLoaders со своими собственными кэшами с одним изображением. Таким образом, в его значении не будет никакого кэширования.

Чтобы решить эту проблему, после создания экземпляра ImageLoader вам следует сохранить ссылку на него в переменной класса / структуры, которая его потребляет, и передать ее другому потребителю. кому нужен такой же кеш. (Техника внедрения зависимостей c является хорошим подходом для этого). Таким образом, один кэш с некоторым количеством элементов будет существовать и работать.

Или самый простой способ - создать общий экземпляр ImageLoader и использовать его только, таким образом, он также гарантирует один экземпляр с одним заполненным кешем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...