@@ -44,7 +44,7 @@ final class AnimatedLoadingModel : ObservableObject, IndicatorReportable {
4444 @Published var isLoading : Bool = false // whether network is loading or cache is querying, should only be used for indicator binding
4545 @Published var progress : Double = 0 // network progress, should only be used for indicator binding
4646
47- /// Used for loading status recording to avoid recursive `updateView`. There are 3 types of loading (Name/Data/URL)
47+ /// Used for loading status recording to avoid recursive `updateView`. There are 3 types of loading (Name/Data/URL)
4848 @Published var imageName : String ?
4949 @Published var imageData : Data ?
5050 @Published var imageURL : URL ?
@@ -206,12 +206,27 @@ public struct AnimatedImage : PlatformViewRepresentable {
206206 }
207207 #endif
208208
209- func loadImage( _ view: AnimatedImageViewWrapper , context: Context ) {
210- let operationKey = NSStringFromClass ( type ( of: view. wrapped) )
211- let currentOperation = view. wrapped. sd_imageLoadOperation ( forKey: operationKey)
212- if currentOperation != nil {
213- return
209+ func setupIndicator( _ view: AnimatedImageViewWrapper , context: Context ) {
210+ view. wrapped. sd_imageIndicator = imageConfiguration. indicator
211+ view. wrapped. sd_imageTransition = imageConfiguration. transition
212+ if let placeholderView = imageConfiguration. placeholderView {
213+ placeholderView. removeFromSuperview ( )
214+ placeholderView. isHidden = true
215+ // Placeholder View should below the Indicator View
216+ if let indicatorView = imageConfiguration. indicator? . indicatorView {
217+ #if os(macOS)
218+ view. wrapped. addSubview ( placeholderView, positioned: . below, relativeTo: indicatorView)
219+ #else
220+ view. wrapped. insertSubview ( placeholderView, belowSubview: indicatorView)
221+ #endif
222+ } else {
223+ view. wrapped. addSubview ( placeholderView)
224+ }
225+ placeholderView. bindFrameToSuperviewBounds ( )
214226 }
227+ }
228+
229+ func loadImage( _ view: AnimatedImageViewWrapper , context: Context ) {
215230 self . imageLoading. isLoading = true
216231 let options = imageModel. webOptions
217232 if options. contains ( . delayPlaceholder) {
@@ -234,9 +249,9 @@ public struct AnimatedImage : PlatformViewRepresentable {
234249 self . imageHandler. progressBlock ? ( receivedSize, expectedSize)
235250 } ) { ( image, data, error, cacheType, finished, _) in
236251 if #available( iOS 14 . 0 , macOS 11 . 0 , watchOS 7 . 0 , tvOS 14 . 0 , * ) {
237- // Do nothing
252+ // Do nothing. on iOS 14's SwiftUI, the @Published will always trigger another `updateUIView` call with new UIView instance.
238253 } else {
239- // This is a hack because of Xcode 11.3 bug, the @Published does not trigger another `updateUIView` call
254+ // This is a hack because of iOS 13's SwiftUI bug, the @Published does not trigger another `updateUIView` call
240255 // Here I have to use UIKit/AppKit API to triger the same effect (the window change implicitly cause re-render)
241256 if let hostingView = AnimatedImage . findHostingView ( from: view) {
242257 if let _ = hostingView. window {
@@ -284,26 +299,28 @@ public struct AnimatedImage : PlatformViewRepresentable {
284299 let image = SDAnimatedImage ( data: data, scale: imageModel. scale)
285300 imageLoading. imageData = data
286301 view. wrapped. image = image
287- } else if let url = imageModel. url, url != imageLoading . imageURL {
288- imageLoading . imageURL = url
289- view . wrapped . sd_imageIndicator = imageConfiguration . indicator
290- view . wrapped . sd_imageTransition = imageConfiguration . transition
291- if let placeholderView = imageConfiguration . placeholderView {
292- placeholderView . removeFromSuperview ( )
293- placeholderView . isHidden = true
294- // Placeholder View should below the Indicator View
295- if let indicatorView = imageConfiguration . indicator ? . indicatorView {
296- # if os(macOS)
297- view . wrapped . addSubview ( placeholderView , positioned : . below , relativeTo : indicatorView )
298- #else
299- view . wrapped . insertSubview ( placeholderView , belowSubview : indicatorView )
300- #endif
302+ } else if let url = imageModel. url {
303+ // Determine if image already been loaded and URL is match
304+ var shouldLoad : Bool
305+ if url != imageLoading . imageURL {
306+ // Change the URL, need new loading
307+ shouldLoad = true
308+ imageLoading . imageURL = url
309+ } else {
310+ // Same URL, check if already loaded
311+ if imageLoading . isLoading {
312+ shouldLoad = false
313+ } else if let image = imageLoading . image {
314+ shouldLoad = false
315+ view . wrapped . image = image
301316 } else {
302- view . wrapped . addSubview ( placeholderView )
317+ shouldLoad = true
303318 }
304- placeholderView. bindFrameToSuperviewBounds ( )
305319 }
306- loadImage ( view, context: context)
320+ if shouldLoad {
321+ setupIndicator ( view, context: context)
322+ loadImage ( view, context: context)
323+ }
307324 }
308325
309326 #if os(macOS)
0 commit comments