@@ -14,8 +14,8 @@ import SDWebImage
14
14
final class WebImageModel : ObservableObject {
15
15
/// URL image
16
16
@Published var url : URL ?
17
- @Published var webOptions : SDWebImageOptions = [ ]
18
- @Published var webContext : [ SDWebImageContextOption : Any ] ? = nil
17
+ @Published var options : SDWebImageOptions = [ ]
18
+ @Published var context : [ SDWebImageContextOption : Any ] ? = nil
19
19
}
20
20
21
21
/// Completion Handler Binding Object, supports dynamic @State changes
@@ -61,11 +61,13 @@ public struct WebImage : View {
61
61
/// A observed object to pass through the image configuration to player
62
62
@ObservedObject var imageConfiguration = WebImageConfiguration ( )
63
63
64
+ @ObservedObject var indicatorStatus : IndicatorStatus
65
+
64
66
// FIXME: Use SwiftUI StateObject and remove onPlatformAppear once drop iOS 13 support
65
67
@Backport . StateObject var imagePlayer = ImagePlayer ( )
66
68
67
69
// FIXME: Use SwiftUI StateObject and remove onPlatformAppear once drop iOS 13 support
68
- @Backport . StateObject var imageManager = ImageManager ( )
70
+ @Backport . StateObject var imageManager : ImageManager
69
71
70
72
/// Create a web image with url, placeholder, custom options and context. Optional can support animated image using Binding.
71
73
/// - Parameter url: The image url
@@ -83,9 +85,12 @@ public struct WebImage : View {
83
85
}
84
86
let imageModel = WebImageModel ( )
85
87
imageModel. url = url
86
- imageModel. webOptions = options
87
- imageModel. webContext = context
88
+ imageModel. options = options
89
+ imageModel. context = context
88
90
_imageModel = ObservedObject ( wrappedValue: imageModel)
91
+ let imageManager = ImageManager ( )
92
+ _imageManager = Backport . StateObject ( wrappedValue: imageManager)
93
+ _indicatorStatus = ObservedObject ( wrappedValue: imageManager. indicatorStatus)
89
94
}
90
95
91
96
/// Create a web image with url, placeholder, custom options and context.
@@ -98,7 +103,7 @@ public struct WebImage : View {
98
103
99
104
public var body : some View {
100
105
return Group {
101
- if let image = imageManager. image {
106
+ if imageManager . image != nil && imageModel . url == imageManager. currentURL {
102
107
if isAnimating && !imageManager. isIncremental {
103
108
setupPlayer ( )
104
109
. onDisappear {
@@ -118,7 +123,7 @@ public struct WebImage : View {
118
123
if let currentFrame = imagePlayer. currentFrame {
119
124
configure ( image: currentFrame)
120
125
} else {
121
- configure ( image: image)
126
+ configure ( image: imageManager . image! )
122
127
}
123
128
}
124
129
} else {
@@ -127,17 +132,19 @@ public struct WebImage : View {
127
132
self . imageManager. successBlock = self . imageHandler. successBlock
128
133
self . imageManager. failureBlock = self . imageHandler. failureBlock
129
134
self . imageManager. progressBlock = self . imageHandler. progressBlock
130
- // Load remote image when first appear
131
- self . imageManager. load ( url: imageModel. url, options: imageModel. webOptions, context: imageModel. webContext)
135
+ if ( self . imageManager. error == nil ) {
136
+ // Load remote image when first appear
137
+ self . imageManager. load ( url: imageModel. url, options: imageModel. options, context: imageModel. context)
138
+ }
132
139
guard self . imageConfiguration. retryOnAppear else { return }
133
140
// When using prorgessive loading, the new partial image will cause onAppear. Filter this case
134
- if self . imageManager. image = = nil && !self . imageManager. isIncremental {
135
- self . imageManager. load ( url: imageModel. url, options: imageModel. webOptions , context: imageModel. webContext )
141
+ if self . imageManager. error ! = nil && !self . imageManager. isIncremental {
142
+ self . imageManager. load ( url: imageModel. url, options: imageModel. options , context: imageModel. context )
136
143
}
137
144
} , disappear: {
138
145
guard self . imageConfiguration. cancelOnDisappear else { return }
139
146
// When using prorgessive loading, the previous partial image will cause onDisappear. Filter this case
140
- if self . imageManager. image = = nil && !self . imageManager. isIncremental {
147
+ if self . imageManager. error ! = nil && !self . imageManager. isIncremental {
141
148
self . imageManager. cancel ( )
142
149
}
143
150
} )
@@ -196,18 +203,25 @@ public struct WebImage : View {
196
203
197
204
/// Animated Image Support
198
205
func setupPlayer( ) -> some View {
199
- if let currentFrame = imagePlayer. currentFrame {
206
+ if let currentFrame = imagePlayer. currentFrame, imagePlayer . currentAnimatedImage == imageManager . image! {
200
207
return configure ( image: currentFrame) . onAppear {
201
208
self . imagePlayer. startPlaying ( )
202
209
}
203
210
} else {
204
211
return configure ( image: imageManager. image!) . onAppear {
205
- if let animatedImage = imageManager. image as? SDAnimatedImageProvider {
212
+ self . imagePlayer. stopPlaying ( )
213
+ if let animatedImage = imageManager. image as? PlatformImage & SDAnimatedImageProvider {
214
+ // Clear previous status
215
+ self . imagePlayer. player = nil ;
216
+ self . imagePlayer. currentFrame = nil ;
217
+ self . imagePlayer. currentFrameIndex = 0 ;
218
+ self . imagePlayer. currentLoopCount = 0 ;
206
219
self . imagePlayer. customLoopCount = self . imageConfiguration. customLoopCount
207
220
self . imagePlayer. maxBufferSize = self . imageConfiguration. maxBufferSize
208
221
self . imagePlayer. runLoopMode = self . imageConfiguration. runLoopMode
209
222
self . imagePlayer. playbackMode = self . imageConfiguration. playbackMode
210
223
self . imagePlayer. playbackRate = self . imageConfiguration. playbackRate
224
+ // Setup new player
211
225
self . imagePlayer. setupPlayer ( animatedImage: animatedImage)
212
226
self . imagePlayer. startPlaying ( )
213
227
}
@@ -220,7 +234,7 @@ public struct WebImage : View {
220
234
// Don't use `Group` because it will trigger `.onAppear` and `.onDisappear` when condition view removed, treat placeholder as an entire component
221
235
if let placeholder = placeholder {
222
236
// If use `.delayPlaceholder`, the placeholder is applied after loading failed, hide during loading :)
223
- if imageModel. webOptions . contains ( . delayPlaceholder) && imageManager. error == nil {
237
+ if imageModel. options . contains ( . delayPlaceholder) && imageManager. error == nil {
224
238
return AnyView ( configure ( image: . empty) )
225
239
} else {
226
240
return placeholder
@@ -347,7 +361,7 @@ extension WebImage {
347
361
/// Associate a indicator when loading image with url
348
362
/// - Parameter indicator: The indicator type, see `Indicator`
349
363
public func indicator< T> ( _ indicator: Indicator < T > ) -> some View where T : View {
350
- return self . modifier ( IndicatorViewModifier ( status: imageManager . indicatorStatus, indicator: indicator) )
364
+ return self . modifier ( IndicatorViewModifier ( status: indicatorStatus, indicator: indicator) )
351
365
}
352
366
353
367
/// Associate a indicator when loading image with url, convenient method with block
0 commit comments