Skip to content

Commit d9fd472

Browse files
committed
Using a more trick but smart solution for cases when WebImage is used during transition state, like scaleEffect. In this time, we does not trigger a actualy image loading, only query the memory cache for quickly placeholder
1 parent 0b11cce commit d9fd472

File tree

3 files changed

+30
-11
lines changed

3 files changed

+30
-11
lines changed

Example/SDWebImageSwiftUIDemo/DetailView.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ struct DetailView: View {
3838
let url: String
3939
let animated: Bool
4040
@State var isAnimating: Bool = true
41-
@State var lastScaleValue: CGFloat = 1.0
41+
@State var lastScale: CGFloat = 1.0
4242
@State var scale: CGFloat = 1.0
4343
@Environment(\.presentationMode) var presentationMode
4444
@EnvironmentObject var settings: UserSettings
@@ -75,12 +75,12 @@ struct DetailView: View {
7575
return contentView()
7676
.scaleEffect(self.scale)
7777
.gesture(MagnificationGesture(minimumScaleDelta: 0.1).onChanged { value in
78-
let delta = value / self.lastScaleValue
79-
self.lastScaleValue = value
78+
let delta = value / self.lastScale
79+
self.lastScale = value
8080
let newScale = self.scale * delta
8181
self.scale = min(max(newScale, 0.5), 2)
8282
}.onEnded { value in
83-
self.lastScaleValue = 1.0
83+
self.lastScale = 1.0
8484
})
8585
#endif
8686
#if os(tvOS)

SDWebImageSwiftUI/Classes/ImageManager.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,23 @@ public final class ImageManager : ObservableObject {
106106
}
107107
}
108108

109+
/// Prefetch the initial state of image
110+
internal func prefetch() {
111+
let key = manager.cacheKey(for: url)
112+
if let imageCache = manager.imageCache as? SDImageCache {
113+
self.image = imageCache.imageFromMemoryCache(forKey: key)
114+
} else {
115+
// generic API
116+
manager.imageCache.containsImage(forKey: key, cacheType: .memory) { [unowned self] (cacheType) in
117+
if cacheType == .memory {
118+
self.manager.imageCache.queryImage(forKey: key, options: self.options, context: self.context) { [unowned self] (image, data, cacheType) in
119+
self.image = image
120+
}
121+
}
122+
}
123+
}
124+
}
125+
109126
}
110127

111128
// Completion Handler

SDWebImageSwiftUI/Classes/WebImage.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,13 @@ public struct WebImage : View {
5757
}
5858
}
5959
self.imageManager = ImageManager(url: url, options: options, context: context)
60+
// this prefetch the memory cache of image, to immediately render it on screen
61+
// this solve the cause when `onAppear` not been called, for example, some transaction indetermite state :)
62+
self.imageManager.prefetch()
6063
}
6164

6265
public var body: some View {
63-
// load remote image when first called `body`, SwiftUI sometimes will create a new View struct without calling `onAppear` (like enter EditMode) :)
64-
// this can ensure we load the image, and display image synchronously when memory cache hit to avoid flashing
65-
// called once per struct, SDWebImage take care of the duplicated query
66-
if imageManager.isFirstLoad {
67-
imageManager.load()
68-
}
69-
return Group {
66+
Group {
7067
if imageManager.image != nil {
7168
if isAnimating && !self.imageManager.isIncremental {
7269
if currentFrame != nil {
@@ -109,6 +106,11 @@ public struct WebImage : View {
109106
setupPlaceholder()
110107
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
111108
.onAppear {
109+
// load remote image when first appear
110+
if self.imageManager.isFirstLoad {
111+
self.imageManager.load()
112+
return
113+
}
112114
guard self.retryOnAppear else { return }
113115
// When using prorgessive loading, the new partial image will cause onAppear. Filter this case
114116
if self.imageManager.image == nil && !self.imageManager.isIncremental {

0 commit comments

Comments
 (0)