Don't crash when the GIF data provider is invoked off the main thread

LoadableImageContent.data(handler:) used MainActor.assumeIsolated to read
the loader's content, which crashes (libdispatch precondition) when
Kingfisher invokes the provider off the main thread, and fatalError'd
when the content wasn't GIF data. Hop onto the main actor and return a
failure instead. The handler is @Sendable per Kingfisher's protocol.
This commit is contained in:
Stefan Ceriu
2026-06-22 14:18:53 +03:00
parent b4fe69a0c9
commit 101fc7573b
@@ -234,23 +234,24 @@ private struct LoadableImageContent<TransformerView: View, PlaceholderView: View
mediaSource.url.absoluteString
}
nonisolated func data(handler: @escaping (Result<Data, Error>) -> Void) {
// Kingfisher isn't annotated but invokes the provider on the main thread.
let gifData = MainActor.assumeIsolated { () -> Data? in
nonisolated func data(handler: @escaping @Sendable (Result<Data, Error>) -> Void) {
// Kingfisher isn't annotated and doesn't guarantee the provider is invoked on the main
// thread so hop onto the main actor.
Task { @MainActor in
guard case let .gifData(data) = contentLoader.content else {
return nil
handler(.failure(LoadableImageError.missingGIFData))
return
}
return data
handler(.success(data))
}
guard let gifData else {
fatalError("Shouldn't reach this point without any gif data")
}
handler(.success(gifData))
}
}
private enum LoadableImageError: Error {
case missingGIFData
}
private class ContentLoader: ObservableObject {
enum Content: Equatable {
case image(UIImage)