@@ -27,6 +27,13 @@ public final class AnimatedImageCoordinator: NSObject {
27
27
/// Data Binding Object, only properties in this object can support changes from user with @State and refresh
28
28
@available ( iOS 14 . 0 , OSX 11 . 0 , tvOS 14 . 0 , watchOS 7 . 0 , * )
29
29
final class AnimatedImageModel : ObservableObject {
30
+ enum Kind {
31
+ case url
32
+ case data
33
+ case name
34
+ case unknown
35
+ }
36
+ var kind : Kind = . unknown
30
37
/// URL image
31
38
@Published var url : URL ?
32
39
@Published var webOptions : SDWebImageOptions = [ ]
@@ -123,6 +130,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
123
130
/// - Parameter isAnimating: The binding for animation control
124
131
public init ( url: URL ? , options: SDWebImageOptions = [ ] , context: [ SDWebImageContextOption : Any ] ? = nil , isAnimating: Binding < Bool > = . constant( true ) , placeholderImage: PlatformImage ? = nil ) {
125
132
let imageModel = AnimatedImageModel ( )
133
+ imageModel. kind = . url
126
134
imageModel. url = url
127
135
imageModel. webOptions = options
128
136
imageModel. webContext = context
@@ -138,6 +146,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
138
146
/// - Parameter isAnimating: The binding for animation control
139
147
public init < T> ( url: URL ? , options: SDWebImageOptions = [ ] , context: [ SDWebImageContextOption : Any ] ? = nil , isAnimating: Binding < Bool > = . constant( true ) , @ViewBuilder placeholder: @escaping ( ) -> T ) where T : View {
140
148
let imageModel = AnimatedImageModel ( )
149
+ imageModel. kind = . url
141
150
imageModel. url = url
142
151
imageModel. webOptions = options
143
152
imageModel. webContext = context
@@ -157,6 +166,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
157
166
/// - Parameter isAnimating: The binding for animation control
158
167
public init ( name: String , bundle: Bundle ? = nil , isAnimating: Binding < Bool > = . constant( true ) ) {
159
168
let imageModel = AnimatedImageModel ( )
169
+ imageModel. kind = . name
160
170
imageModel. name = name
161
171
imageModel. bundle = bundle
162
172
self . init ( imageModel: imageModel, isAnimating: isAnimating)
@@ -168,6 +178,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
168
178
/// - Parameter isAnimating: The binding for animation control
169
179
public init ( data: Data , scale: CGFloat = 1 , isAnimating: Binding < Bool > = . constant( true ) ) {
170
180
let imageModel = AnimatedImageModel ( )
181
+ imageModel. kind = . data
171
182
imageModel. data = data
172
183
imageModel. scale = scale
173
184
self . init ( imageModel: imageModel, isAnimating: isAnimating)
@@ -275,57 +286,72 @@ public struct AnimatedImage : PlatformViewRepresentable {
275
286
return view
276
287
}
277
288
289
+ private func updateViewForName( _ name: String , view: AnimatedImageViewWrapper , context: Context ) {
290
+ var image : PlatformImage ?
291
+ #if os(macOS)
292
+ image = SDAnimatedImage ( named: name, in: imageModel. bundle)
293
+ if image == nil {
294
+ // For static image, use NSImage as defaults
295
+ let bundle = imageModel. bundle ?? . main
296
+ image = bundle. image ( forResource: name)
297
+ }
298
+ #else
299
+ image = SDAnimatedImage ( named: name, in: imageModel. bundle, compatibleWith: nil )
300
+ if image == nil {
301
+ // For static image, use UIImage as defaults
302
+ image = PlatformImage ( named: name, in: imageModel. bundle, compatibleWith: nil )
303
+ }
304
+ #endif
305
+ context. coordinator. imageLoading. imageName = name
306
+ view. wrapped. image = image
307
+ }
308
+
309
+ private func updateViewForData( _ data: Data , view: AnimatedImageViewWrapper , context: Context ) {
310
+ var image : PlatformImage ? = SDAnimatedImage ( data: data, scale: imageModel. scale)
311
+ if image == nil {
312
+ // For static image, use UIImage as defaults
313
+ image = PlatformImage . sd_image ( with: data, scale: imageModel. scale)
314
+ }
315
+ context. coordinator. imageLoading. imageData = data
316
+ view. wrapped. image = image
317
+ }
318
+
319
+ private func updateViewForURL( _ url: URL ? , view: AnimatedImageViewWrapper , context: Context ) {
320
+ // Determine if image already been loaded and URL is match
321
+ var shouldLoad : Bool
322
+ if url != context. coordinator. imageLoading. imageURL {
323
+ // Change the URL, need new loading
324
+ shouldLoad = true
325
+ context. coordinator. imageLoading. imageURL = url
326
+ } else {
327
+ // Same URL, check if already loaded
328
+ if context. coordinator. imageLoading. isLoading {
329
+ shouldLoad = false
330
+ } else if let image = context. coordinator. imageLoading. image {
331
+ shouldLoad = false
332
+ view. wrapped. image = image
333
+ } else {
334
+ shouldLoad = true
335
+ }
336
+ }
337
+ if shouldLoad {
338
+ setupIndicator ( view, context: context)
339
+ loadImage ( view, context: context)
340
+ }
341
+ }
342
+
278
343
func updateView( _ view: AnimatedImageViewWrapper , context: Context ) {
279
344
// Refresh image, imageModel is the Source of Truth, switch the type
280
345
// Although we have Source of Truth, we can check the previous value, to avoid re-generate SDAnimatedImage, which is performance-cost.
281
- if let name = imageModel. name, name != context. coordinator. imageLoading. imageName {
282
- var image : PlatformImage ?
283
- #if os(macOS)
284
- image = SDAnimatedImage ( named: name, in: imageModel. bundle)
285
- if image == nil {
286
- // For static image, use NSImage as defaults
287
- let bundle = imageModel. bundle ?? . main
288
- image = bundle. image ( forResource: name)
289
- }
290
- #else
291
- image = SDAnimatedImage ( named: name, in: imageModel. bundle, compatibleWith: nil )
292
- if image == nil {
293
- // For static image, use UIImage as defaults
294
- image = PlatformImage ( named: name, in: imageModel. bundle, compatibleWith: nil )
295
- }
296
- #endif
297
- context. coordinator. imageLoading. imageName = name
298
- view. wrapped. image = image
299
- } else if let data = imageModel. data, data != context. coordinator. imageLoading. imageData {
300
- var image : PlatformImage ? = SDAnimatedImage ( data: data, scale: imageModel. scale)
301
- if image == nil {
302
- // For static image, use UIImage as defaults
303
- image = PlatformImage . sd_image ( with: data, scale: imageModel. scale)
304
- }
305
- context. coordinator. imageLoading. imageData = data
306
- view. wrapped. image = image
307
- } else if let url = imageModel. url {
308
- // Determine if image already been loaded and URL is match
309
- var shouldLoad : Bool
310
- if url != context. coordinator. imageLoading. imageURL {
311
- // Change the URL, need new loading
312
- shouldLoad = true
313
- context. coordinator. imageLoading. imageURL = url
314
- } else {
315
- // Same URL, check if already loaded
316
- if context. coordinator. imageLoading. isLoading {
317
- shouldLoad = false
318
- } else if let image = context. coordinator. imageLoading. image {
319
- shouldLoad = false
320
- view. wrapped. image = image
321
- } else {
322
- shouldLoad = true
323
- }
324
- }
325
- if shouldLoad {
326
- setupIndicator ( view, context: context)
327
- loadImage ( view, context: context)
328
- }
346
+ let kind = imageModel. kind
347
+ if kind == . name, let name = imageModel. name, name != context. coordinator. imageLoading. imageName {
348
+ updateViewForName ( name, view: view, context: context)
349
+ } else if kind == . data, let data = imageModel. data, data != context. coordinator. imageLoading. imageData {
350
+ updateViewForData ( data, view: view, context: context)
351
+ } else if kind == . url {
352
+ updateViewForURL ( imageModel. url, view: view, context: context)
353
+ } else {
354
+ fatalError ( " Unsupport model kind: \( kind) " )
329
355
}
330
356
331
357
#if os(macOS)
0 commit comments