@@ -102,8 +102,17 @@ public struct WebImage : View {
102
102
}
103
103
104
104
public var body : some View {
105
- return Group {
106
- // Render Logic
105
+ // Container
106
+ return ZStack {
107
+ // This empty Image is used to receive container's level appear/disappear to start/stop player, reduce CPU usage
108
+ Image ( platformImage: . empty)
109
+ . onAppear {
110
+ self . appearAction ( )
111
+ }
112
+ . onDisappear {
113
+ self . disappearAction ( )
114
+ }
115
+ // Render Logic for actual animated image frame or static image
107
116
if imageManager. image != nil && imageModel. url == imageManager. currentURL {
108
117
if isAnimating && !imageManager. isIncremental {
109
118
setupPlayer ( )
@@ -118,7 +127,7 @@ public struct WebImage : View {
118
127
// Load Logic
119
128
setupPlaceholder ( )
120
129
. onPlatformAppear ( appear: {
121
- setupManager ( )
130
+ self . setupManager ( )
122
131
if ( self . imageManager. error == nil ) {
123
132
// Load remote image when first appear
124
133
self . imageManager. load ( url: imageModel. url, options: imageModel. options, context: imageModel. context)
@@ -205,36 +214,50 @@ public struct WebImage : View {
205
214
}
206
215
}
207
216
217
+ /// Container level to resume animation when appear
218
+ func appearAction( ) {
219
+ self . imagePlayer. startPlaying ( )
220
+ }
221
+
222
+ /// Container level to stop animation when disappear
223
+ func disappearAction( ) {
224
+ if self . imageConfiguration. pausable {
225
+ self . imagePlayer. pausePlaying ( )
226
+ } else {
227
+ self . imagePlayer. stopPlaying ( )
228
+ }
229
+ if self . imageConfiguration. purgeable {
230
+ self . imagePlayer. clearFrameBuffer ( )
231
+ }
232
+ }
233
+
208
234
/// Animated Image Support
209
235
func setupPlayer( ) -> some View {
210
- let disappearAction = {
211
- // Only stop the player which is not intermediate status
212
- if !imagePlayer. isWaiting {
213
- if self . imageConfiguration. pausable {
214
- self . imagePlayer. pausePlaying ( )
215
- } else {
216
- self . imagePlayer. stopPlaying ( )
217
- }
218
- if self . imageConfiguration. purgeable {
219
- self . imagePlayer. clearFrameBuffer ( )
220
- }
221
- }
236
+ let shouldResetPlayer : Bool
237
+ // Image compare should use ===/!==, which is faster than isEqual:
238
+ if let animatedImage = imagePlayer. currentAnimatedImage, animatedImage !== imageManager. image! {
239
+ shouldResetPlayer = true
240
+ } else {
241
+ shouldResetPlayer = false
222
242
}
223
- if let currentFrame = imagePlayer. currentFrame, imagePlayer. currentAnimatedImage == imageManager. image! {
224
- return configure ( image: currentFrame) . onPlatformAppear ( appear: {
225
- self . imagePlayer. startPlaying ( )
226
- } , disappear: {
227
- disappearAction ( )
228
- } )
243
+ if let currentFrame = imagePlayer. currentFrame, !shouldResetPlayer {
244
+ // Bind frame index to ID to ensure onDisappear called with sync
245
+ return configure ( image: currentFrame)
246
+ . id ( " \( imageModel. url!) : \( imagePlayer. currentFrameIndex) " )
247
+ . onAppear { }
229
248
} else {
230
- return configure ( image: imageManager. image!) . onPlatformAppear ( appear: {
231
- self . imagePlayer. stopPlaying ( )
232
- if let animatedImage = imageManager. image as? PlatformImage & SDAnimatedImageProvider {
249
+ return configure ( image: imageManager. image!)
250
+ . id ( " \( imageModel. url!) : \( imagePlayer. currentFrameIndex) " )
251
+ . onAppear {
252
+ if shouldResetPlayer {
233
253
// Clear previous status
234
- self . imagePlayer. player = nil ;
254
+ self . imagePlayer. stopPlaying ( )
255
+ self . imagePlayer. player = nil
235
256
self . imagePlayer. currentFrame = nil ;
236
257
self . imagePlayer. currentFrameIndex = 0 ;
237
258
self . imagePlayer. currentLoopCount = 0 ;
259
+ }
260
+ if let animatedImage = imageManager. image as? PlatformImage & SDAnimatedImageProvider {
238
261
self . imagePlayer. customLoopCount = self . imageConfiguration. customLoopCount
239
262
self . imagePlayer. maxBufferSize = self . imageConfiguration. maxBufferSize
240
263
self . imagePlayer. runLoopMode = self . imageConfiguration. runLoopMode
@@ -244,9 +267,7 @@ public struct WebImage : View {
244
267
self . imagePlayer. setupPlayer ( animatedImage: animatedImage)
245
268
self . imagePlayer. startPlaying ( )
246
269
}
247
- } , disappear: {
248
- disappearAction ( )
249
- } )
270
+ }
250
271
}
251
272
}
252
273
0 commit comments