1
0
mirror of https://github.com/mastodon/mastodon-ios.git synced 2025-02-03 02:37:37 +01:00

Make sure not to display an image that belongs to a different post

The key change here is to store the image subscription in the MediaView’s disposeBag rather than the configuration’s, so that it is properly disposed of in the MediaView’s prepareForReuse().

For good measure, also adding MainActor on prepareForReuse and actual cancellation of all subscriptions before releasing them.

Fixes #1374 [BUG] Posts can load the wrong images
This commit is contained in:
shannon 2024-12-10 11:16:43 -05:00
parent 9e24af509e
commit ca6ecd13aa

View File

@ -127,7 +127,8 @@ extension MediaView {
layoutAlt()
}
private func bindImage(configuration: Configuration, info: Configuration.ImageInfo) {
private func bindImage(configuration: Configuration, info: Configuration.ImageInfo) {
let subscribedConfigurationIdentifier = ObjectIdentifier(configuration) // this shouldn't be necessary now, but allows a check in debug mode. https://github.com/mastodon/mastodon-ios/issues/1374
Publishers.CombineLatest(
configuration.$previewImage,
configuration.$blurhashImage
@ -135,13 +136,16 @@ extension MediaView {
.receive(on: DispatchQueue.main)
.sink { [weak self] previewImage, blurhashImage in
guard let self = self else { return }
guard let currentConfiguration = self.configuration, ObjectIdentifier(currentConfiguration) == subscribedConfigurationIdentifier else {
assert(false, "\(self) attempt to load an image that belongs to a configuration no longer associated with this MediaView.")
return
}
let image = configuration.isReveal ?
(previewImage ?? blurhashImage ?? MediaView.placeholderImage) :
(blurhashImage ?? MediaView.placeholderImage)
self.imageView.image = image
}
.store(in: &configuration.disposeBag)
.store(in: &_disposeBag)
bindAlt(configuration: configuration, altDescription: info.altDescription)
}
@ -220,7 +224,11 @@ extension MediaView {
overlayViewController.view.pinToParent()
}
@MainActor
public func prepareForReuse() {
for cancellable in _disposeBag {
cancellable.cancel()
}
_disposeBag.removeAll()
// reset appearance