-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
app crashs on iOS 14 when use Kingfisher in List #1508
Comments
Hi, Thanks for letting me know this. But I tried the SwiftUI List demo in the project and it seems working well and no crash happens. Is it only on real devices or also on simulators? Do you have a sample view or some code snippet that we can use to reproduce it? Thank you! |
Hello and thanks for the fast reply. After some more investigations I found out, that it only occurs on device, and only if the I updated the import class Kingfisher.ImageCache
import KingfisherSwiftUI
import SwiftUI
struct SwiftUIList : View {
let index = 1 ..< 700
var body: some View {
NavigationView{
List(index) { i in
ListCell(index: i)
}.navigationBarTitle(Text("SwiftUI List"), displayMode: .inline)
}
}
struct ListCell: View {
let index: Int
var body: some View {
NavigationLink(destination: Text("\(index)")) {
ListCellImage(index: index)
.scaledToFit()
.frame(maxWidth: 100, maxHeight: 100)
}
}
}
struct ListCellImage: View {
@State var done = false
var alreadyCached: Bool {
ImageCache.default.isCached(forKey: url.absoluteString)
}
let index: Int
var url: URL {
URL(string: "https://github.com/onevcat/Flower-Data-Set/raw/master/rose/rose-\(index).jpg")!
}
var body: some View {
HStack(alignment: .center) {
Spacer()
KFImage(url, isLoaded: $done)
.resizable()
.onSuccess { r in
print("Success: \(self.index) - \(r.cacheType)")
}
.onFailure { e in
print("Error \(self.index): \(e)")
}
.onProgress { downloaded, total in
print("\(downloaded) / \(total))")
}
.placeholder {
HStack {
Image(systemName: "arrow.2.circlepath.circle")
.resizable()
.frame(width: 50, height: 50)
.padding(10)
Text("Loading...").font(.title)
}
.foregroundColor(.gray)
}
.cancelOnDisappear(true)
.aspectRatio(contentMode: .fit)
.cornerRadius(20)
.frame(width: 300, height: 300)
.opacity(done || alreadyCached ? 1.0 : 0.3)
.animation(.linear(duration: 0.4))
Spacer()
}.padding(.vertical, 12)
}
}
}
#if DEBUG
struct SwiftUIList_Previews : PreviewProvider {
static var previews: some View {
SwiftUIList()
}
}
#endif |
Hi ! Also, it's worth to mention that in some cases it's not crashing immediately but only after few rows are loaded. |
@hassfers @RosayGaspard Thanks for this information. I tried the sample above and it did give me a crash when building with Xcode 12 and run on iOS 14. But if I build it using Xcode 11, or build with Xcode 12 but run on iOS 13, the code does not give a crash. To me, it seems that this issue only happens on iOS 14. Am I missing something or do you have the same situation? @RosayGaspard Thank you for your kindly report.
Oh, it is already on AppStore, so I guess it is also happening on iOS 13? The crash stack I can get when running on iOS 14 indicates an internal layout error under UIKit. Maybe it is related to something like cell reuse or frame calculation. Can you paste something like a symbol stack for the crashes on both older iOS 13 devices and new iOS 14? I want to track if we are having the same issue on both system versions. Thank you again! |
@onevcat Sorry I realise my post was a bit confusing. The older version of the app, that is live in the store, works well on iOS 13 devices, it crashes only on iOS14 devices. The problem for me is that iOS14 will certainly be released this week (if not today after the Apple event), so all my users who will update to it will have crashes within the app :( But I think I might have some more information for you: Some of my views also embed Kingfisher elements inside a NavigationLink but only have a few rows (10 to 15 to be exact) and in that case, the views don't crash at all. |
That makes sense. I dig into it a bit deeper, and now I can have a minimal reproducible example as below: struct ContentView: View {
let indexes = 1 ..< 100
var body: some View {
NavigationView {
List(indexes) { i in
NavigationLink(
destination: Text("Index \(i)"),
label: {
HStack { Cell(index: i) }
})
}
}
}
}
struct Cell: View {
@State var loaded = false
let index: Int
var body: some View {
Group {
if loaded {
Text("Loaded: \(index)")
} else {
Text("Loading: \(index)")
}
}.onAppear {
loaded = true
}
}
} This crash happens when embedding any view that can change in an I will try to see if I can give a workaround for it now. But I guess it is more important to report it through feedback/radar (I will do it later today) and expect Apple has a fix on it in the final release. |
I see, thank you for the quick answer ! Hope they'll fix it before the release. |
An obvious, but not always working solution, is not using an List(indexes) { i in
NavigationLink(
destination: Text("Index \(i)"),
label: {
HStack {
Text("Hello ")
Cell(index: i)
}
})
} Do this: List(indexes) { i in
HStack { // <-- Move HStack out!
Text("Hello")
NavigationLink(
destination: Text("Index \(i)"),
label: {
Cell(index: i)
})
}
} (Of course, remember to replace either Until now, I didn't find a (bad) side effect for this workaround, but maybe sometimes there is no way to implement your layout by this. However, it would be better than a crash. Let's see what Apple can do for it in a few days! |
Many many thanks for your deep investigation and your solutions and I'm very sorry for finger pointing 😇 |
I've sent feedback to Apple for this issue. I will leave it open for a while at least until the GM version comes out. Then we can check if there is a real solution for it. |
Unfortunately, it was not fixed in today's Xcode 12 GM. As indicated above, to workaround it, stop using a stack ( List(indexes) { i in
HStack {
Text("Hello ")
Cell(index: i)
}
NavigationLink(
destination: Text("Index \(i)"),
label: {
})
} If you want to see the indicator, using a List(indexes) { i in
HStack {
Text("Hello ")
Cell(index: i)
}
NavigationLink(
destination: Text("Index \(i)"),
label: {
Text("") // Force to show the disclosure indicator
})
} |
I also experience this same issue and would love for it to be fixed! |
@onevcat |
5.15.1 was released for this. |
@onevcat thank you for the quick implementation. Have you tested 5.15.1 in Xcode 11? It seems to throw some errors. I really need the fix in 5.15.1, but I also still need to build my project with Xcode 11. Is there any way you can make it work? |
By the way, I've tried and the issue persists even with Buttons, not just NavigationLinks. |
@lehelmedves However, I am on my vacation now and do not have a Mac at hand to verify it. Please try if that works and if everything goes fine I will tag it in a few days when I return. |
You're fast! Actually, it works only if you put the following for both of your modified lines: |
Oh. I guess it is exactly what I have done? |
Sorry, I misread the file comparison in Git, indeed, exactly what you have done, I missed the naming part. |
Quick follow-up question @onevcat: how does caching work with KFImage? Do I have to do anything special to enable caching? Will caching work and get triggered if I'm using URL's like https://getimage.com?id=25 ? |
Fixed and released as 5.15.2 for this issue. |
|
Sounds great! Thank you for the info! |
Hello
yes I know iOS 14 is still in beta but maybe it helps you ;-)
I use kingfisher in a SwiftUI List to load pictures from urls.
The initial state is shown as expected, but when I start scrolling the app crashs with a
Bad Access
- Error.If I delete the KFImage everything working well.
If I use the same url for every cell it also works fine.
Maybe there is some problem when SwiftUI tries to reuse the Cell and can't load the image somehow.
Does anybody has an idea what to do ?
The text was updated successfully, but these errors were encountered: