Kingfisher: Images not showing up reliably in List on iOS 16
Check List
Thanks for considering to open an issue. Before you submit your issue, please confirm these boxes are checked.
- I have read the wiki page and cheat sheet, but there is no information I need.
- I have searched in existing issues, but did not find a same one.
- I want to report a problem instead of asking a question. It’d better to use kingfisher tag in Stack Overflow to ask a question.
Issue Description
What
On iOS 16 (Xcode 14.0.1), KFImages frequently fail to show up when used inside List/ForEach. We’re using them as part of a more complex list item view, but the bug is reproducible using the very simple code below.
Reproduce
import SwiftUI
import Kingfisher
struct ContentView: View {
private static var imgUrl = URL(string: "https://cdn.iconscout.com/icon/premium/png-48-thumb/kingfisher-3765747-3140298.png")!
var body: some View {
List {
ForEach(1...100, id: \.self) { idx in
KFImage(Self.imgUrl)
.frame(width: 48, height: 48)
}
}
}
}
Scroll around a bit and images will disappear and/or fail to appear.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 28 (14 by maintainers)
Commits related to this issue
- Workaround for #1988 — committed to onevcat/Kingfisher by onevcat 2 years ago
A new version 7.5.0 was released in which this new modifier is contained. I am closing this for now and if Apple can fix it one day I will append some more comments here.
Thank you all for reporting and helping verify it!
I also submitted feedback for it: FB11564208
I will keep an eye on it, but now I have to say there is no good way to fix it on our end.
I can confirm that this issue has been fixed by Apple in Xcode 14.3 (now still in beta) and iOS 16.4. Since that, I will try to add some version checks in the
startLoadingBeforeViewAppearmethod to skip the workaround in newer iOS versions and mark this method as soft-deprecated.I added a method in this
fix/load-before-view-appearbranch. It basically brings back the functionality of loadImmediately back and allows you to load the images as soon as theKFImagebody is evaluated if the image is not yet loaded.I guess it can somehow play as a better workaround before Apple can fix the issue on the SwiftUI side.
To use it:
fix/load-before-view-appearbranchstartLoadingBeforeViewAppear()to theKFImagewhen you encountered this issue:I need some help to try it in more complicate scenes. If it works fine, maybe we can consider including it in the master branch and tagging a release.
@onevcat I can confirm your
fix/load-before-view-appearbranch has fixed this bug. I had this issue with complex UI: a ListView with Sections, and each section having several KFImages. Now the issue is gone, images are loading correctly with your.startLoadingBeforeViewAppear()modifier.Apple’s
AsyncImagehas the same problem, so it seems the cell life cycle in iOS 16 is now totally broken. Not sure if there is a good way to fix it in the third party side, unless we ignore theonAppearbut start the loading in view’sinit. However, it obviously brings other problems such as performance issues.I used 7.3.2 to avoid the workaround, so I think they fixed it for the simplest case.
@rslifka Previously in the dark age of SwiftUI, there was once a
loadImmediatelywhich might be “fixing” this issue. However, it is now removed long ago. Maybe it is actually a good chance to revive it for this issue 😂. I will see if that can work or no.It’s amazing this iOS 16/16.1 bug… I spent some time trying to find a workaround, but it seems very complicated. Only the workaround with the timer worked for me. But as it has an impact on the performance, I preferred to switch from
ListtoScrollView+LazyVStackand it seems working well…Just tried using Xcode 14.1 RC2 and real iOS 16.1 device: the original issue with KFImage directly in List/ForEach seems to be fixed, however the case with nested ForEach-es and Sections is still broken.
Thank you for the many creative workarounds, we will evaluate what to go with.
Sadly 16.1 beta 2 did not fix that much. It fixed this case:
but not this:
and nor this:
I’ve submitted feedback using
AsyncImage. (FB11560572)onAppearindeed helps in that case, but found a more complex one where nothing seems to help: