Skip to content
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

Add an option to start image loading before view appear #2017

Merged
merged 2 commits into from
Jan 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Sources/General/KFOptionsSetter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,7 @@ extension KFOptionSetter {
/// to form a processor pipeline.
/// - Returns: A `Self` value with changes applied.
///
/// - Note:
/// To append processors to current ones instead of replacing them all, concatenate them by `|>`, then use
/// - Note: To append processors to current ones instead of replacing them all, concatenate them by `|>`, then use
/// `appendProcessor(_:)`.
public func setProcessors(_ processors: [ImageProcessor]) -> Self {
switch processors.count {
Expand Down
2 changes: 2 additions & 0 deletions Sources/SwiftUI/ImageContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ extension KFImage {
let onSuccessDelegate = Delegate<RetrieveImageResult, Void>()
let onProgressDelegate = Delegate<(Int64, Int64), Void>()

var startLoadingBeforeViewAppear: Bool = false

init(source: Source?) {
self.source = source
}
Expand Down
20 changes: 20 additions & 0 deletions Sources/SwiftUI/KFImageOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,25 @@ extension KFImageProtocol {
context.options.transition = .fade(duration)
return self
}

/// Sets whether to start the image loading before the view actually appears.
///
/// By default, Kingfisher performs a lazy loading for `KFImage`. The image loading won't start until the view's
/// `onAppear` is called. However, sometimes you may want to trigger an aggressive loading for the view. By enabling
/// this, the `KFImage` will try to load the view when its `body` is evaluated when the image loading is not yet
/// started or a previous loading did fail.
///
/// - Parameter flag: Whether the image loading should happen before view appear. Default is `true`.
/// - Returns: A `KFImage` with changes applied.
///
/// - Note: This is a temporary workaround for an issue from iOS 16, where the SwiftUI view's `onAppear` is not
/// called when it is deeply embedded inside a `List` or `ForEach`.
/// See [#1988](https://github.com/onevcat/Kingfisher/issues/1988). It may cause performance regression, especially
/// if you have a lot of images to load in the view. Use it as your own risk.
///
public func startLoadingBeforeViewAppear(_ flag: Bool = true) -> Self {
context.startLoadingBeforeViewAppear = flag
return self
}
}
#endif
6 changes: 5 additions & 1 deletion Sources/SwiftUI/KFImageRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ struct KFImageRenderer<HoldingView> : View where HoldingView: KFImageHoldingView
let context: KFImage.Context<HoldingView>

var body: some View {
ZStack {
if context.startLoadingBeforeViewAppear && !binder.loadingOrSucceeded {
DispatchQueue.main.async { binder.start(context: context) }
}

return ZStack {
context.configurations
.reduce(HoldingView.created(from: binder.loadedImage, context: context)) {
current, config in config(current)
Expand Down