Skip to content

Commit f720881

Browse files
committed
Update to provide the advanced animated image API for WebImage, fix some API naming for 1.0.0
1 parent 8d74623 commit f720881

File tree

2 files changed

+112
-10
lines changed

2 files changed

+112
-10
lines changed

SDWebImageSwiftUI/Classes/AnimatedImage.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ final class AnimatedImageLayout : ObservableObject {
6666
final class AnimatedImageConfiguration: ObservableObject {
6767
var incrementalLoad: Bool?
6868
var maxBufferSize: UInt?
69-
var customLoopCount: Int?
69+
var customLoopCount: UInt?
7070
var runLoopMode: RunLoop.Mode?
7171
var pausable: Bool?
7272
var purgeable: Bool?
73-
var playBackRate: Double?
73+
var playbackRate: Double?
7474
// These configurations only useful for web image loading
7575
var indicator: SDWebImageIndicator?
7676
var transition: SDWebImageTransition?
@@ -415,7 +415,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
415415
// CustomLoopCount
416416
if let customLoopCount = imageConfiguration.customLoopCount {
417417
view.wrapped.shouldCustomLoopCount = true
418-
view.wrapped.animationRepeatCount = customLoopCount
418+
view.wrapped.animationRepeatCount = Int(customLoopCount)
419419
} else {
420420
// disable custom loop count
421421
view.wrapped.shouldCustomLoopCount = false
@@ -443,8 +443,8 @@ public struct AnimatedImage : PlatformViewRepresentable {
443443
}
444444

445445
// Playback Rate
446-
if let playBackRate = imageConfiguration.playBackRate {
447-
view.wrapped.playbackRate = playBackRate
446+
if let playbackRate = imageConfiguration.playbackRate {
447+
view.wrapped.playbackRate = playbackRate
448448
} else {
449449
view.wrapped.playbackRate = 1.0
450450
}
@@ -557,7 +557,7 @@ extension AnimatedImage {
557557
/// Total loop count for animated image rendering. Defaults to nil.
558558
/// - Note: Pass nil to disable customization, use the image itself loop count (`animatedImageLoopCount`) instead
559559
/// - Parameter loopCount: The animation loop count
560-
public func customLoopCount(_ loopCount: Int?) -> AnimatedImage {
560+
public func customLoopCount(_ loopCount: UInt?) -> AnimatedImage {
561561
self.imageConfiguration.customLoopCount = loopCount
562562
return self
563563
}
@@ -613,9 +613,9 @@ extension AnimatedImage {
613613
/// `0.0-1.0` means the slow speed.
614614
/// `> 1.0` means the fast speed.
615615
/// `< 0.0` is not supported currently and stop animation. (may support reverse playback in the future)
616-
/// - Parameter playBackRate: The animation playback rate.
617-
public func playBackRate(_ playBackRate: Double) -> AnimatedImage {
618-
self.imageConfiguration.playBackRate = playBackRate
616+
/// - Parameter playbackRate: The animation playback rate.
617+
public func playbackRate(_ playbackRate: Double) -> AnimatedImage {
618+
self.imageConfiguration.playbackRate = playbackRate
619619
return self
620620
}
621621
}

SDWebImageSwiftUI/Classes/WebImage.swift

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ public struct WebImage : View {
2828
@State var currentFrame: PlatformImage? = nil
2929
@State var imagePlayer: SDAnimatedImagePlayer? = nil
3030

31+
var incrementalLoad: Bool = true
32+
var maxBufferSize: UInt?
33+
var customLoopCount: UInt?
34+
var runLoopMode: RunLoop.Mode = .common
35+
var pausable: Bool = true
36+
var purgeable: Bool = false
37+
var playbackRate: Double = 1.0
38+
3139
/// Create a web image with url, placeholder, custom options and context.
3240
/// - Parameter url: The image url
3341
/// - Parameter options: The options to use when downloading the image. See `SDWebImageOptions` for the possible values.
@@ -68,7 +76,14 @@ public struct WebImage : View {
6876
self.imagePlayer?.startPlaying()
6977
}
7078
.onDisappear {
71-
self.imagePlayer?.pausePlaying()
79+
if self.pausable {
80+
self.imagePlayer?.pausePlaying()
81+
} else {
82+
self.imagePlayer?.stopPlaying()
83+
}
84+
if self.purgeable {
85+
self.imagePlayer?.clearFrameBuffer()
86+
}
7287
}
7388
} else {
7489
configurations.reduce(Image(platformImage: imageManager.image!)) { (previous, configuration) in
@@ -129,6 +144,16 @@ public struct WebImage : View {
129144
imagePlayer.animationFrameHandler = { (_, frame) in
130145
self.currentFrame = frame
131146
}
147+
// Setup configuration
148+
if let maxBufferSize = maxBufferSize {
149+
imagePlayer.maxBufferSize = maxBufferSize
150+
}
151+
if let customLoopCount = customLoopCount {
152+
imagePlayer.totalLoopCount = UInt(customLoopCount)
153+
}
154+
imagePlayer.runLoopMode = runLoopMode
155+
imagePlayer.playbackRate = playbackRate
156+
132157
self.imagePlayer = imagePlayer
133158
imagePlayer.startPlaying()
134159
}
@@ -264,6 +289,83 @@ extension WebImage {
264289
}
265290
}
266291

292+
// Animated Image
293+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
294+
extension WebImage {
295+
296+
/// Total loop count for animated image rendering. Defaults to nil.
297+
/// - Note: Pass nil to disable customization, use the image itself loop count (`animatedImageLoopCount`) instead
298+
/// - Parameter loopCount: The animation loop count
299+
public func customLoopCount(_ loopCount: UInt?) -> WebImage {
300+
var result = self
301+
result.customLoopCount = loopCount
302+
return result
303+
}
304+
305+
/// Provide a max buffer size by bytes. This is used to adjust frame buffer count and can be useful when the decoding cost is expensive (such as Animated WebP software decoding). Default is nil.
306+
///
307+
/// `0` or nil means automatically adjust by calculating current memory usage.
308+
/// `1` means without any buffer cache, each of frames will be decoded and then be freed after rendering. (Lowest Memory and Highest CPU)
309+
/// `UInt.max` means cache all the buffer. (Lowest CPU and Highest Memory)
310+
/// - Parameter bufferSize: The max buffer size
311+
public func maxBufferSize(_ bufferSize: UInt?) -> WebImage {
312+
var result = self
313+
result.maxBufferSize = bufferSize
314+
return result
315+
}
316+
317+
/// Whehter or not to enable incremental image load for animated image. See `SDAnimatedImageView` for detailed explanation for this.
318+
/// - Note: If you are confused about this description, open Chrome browser to view some large GIF images with low network speed to see the animation behavior.
319+
/// Default is true. Set to false to only render the static poster for incremental animated image.
320+
/// - Parameter incrementalLoad: Whether or not to incremental load
321+
public func incrementalLoad(_ incrementalLoad: Bool) -> WebImage {
322+
var result = self
323+
result.incrementalLoad = incrementalLoad
324+
return result
325+
}
326+
327+
/// The runLoopMode when animation is playing on. Defaults is `.common`
328+
/// You can specify a runloop mode to let it rendering.
329+
/// - Note: This is useful for some cases, for example, always specify NSDefaultRunLoopMode, if you want to pause the animation when user scroll (for Mac user, drag the mouse or touchpad)
330+
/// - Parameter runLoopMode: The runLoopMode for animation
331+
public func runLoopMode(_ runLoopMode: RunLoop.Mode) -> WebImage {
332+
var result = self
333+
result.runLoopMode = runLoopMode
334+
return result
335+
}
336+
337+
/// Whether or not to pause the animation (keep current frame), instead of stop the animation (frame index reset to 0). When `isAnimating` binding value changed to false. Defaults is true.
338+
/// - Note: For some of use case, you may want to reset the frame index to 0 when stop, but some other want to keep the current frame index.
339+
/// - Parameter pausable: Whether or not to pause the animation instead of stop the animation.
340+
public func pausable(_ pausable: Bool) -> WebImage {
341+
var result = self
342+
result.pausable = pausable
343+
return result
344+
}
345+
346+
/// Whether or not to clear frame buffer cache when stopped. Defaults is false.
347+
/// Note: This is useful when you want to limit the memory usage during frequently visibility changes (such as image view inside a list view, then push and pop)
348+
/// - Parameter purgeable: Whether or not to clear frame buffer cache when stopped.
349+
public func purgeable(_ purgeable: Bool) -> WebImage {
350+
var result = self
351+
result.purgeable = purgeable
352+
return result
353+
}
354+
355+
/// Control the animation playback rate. Default is 1.0.
356+
/// `1.0` means the normal speed.
357+
/// `0.0` means stopping the animation.
358+
/// `0.0-1.0` means the slow speed.
359+
/// `> 1.0` means the fast speed.
360+
/// `< 0.0` is not supported currently and stop animation. (may support reverse playback in the future)
361+
/// - Parameter playbackRate: The animation playback rate.
362+
public func playbackRate(_ playbackRate: Double) -> WebImage {
363+
var result = self
364+
result.playbackRate = playbackRate
365+
return result
366+
}
367+
}
368+
267369
#if DEBUG
268370
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
269371
struct WebImage_Previews : PreviewProvider {

0 commit comments

Comments
 (0)