Skip to content

Commit 53e434d

Browse files
committed
Update to provide the advanced animated image API for WebImage, fix some API naming for 1.0.0
1 parent c55336b commit 53e434d

File tree

2 files changed

+114
-10
lines changed

2 files changed

+114
-10
lines changed

SDWebImageSwiftUI/Classes/AnimatedImage.swift

Lines changed: 11 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?
@@ -400,6 +400,8 @@ public struct AnimatedImage : PlatformViewRepresentable {
400400
// IncrementalLoad
401401
if let incrementalLoad = imageConfiguration.incrementalLoad {
402402
view.wrapped.shouldIncrementalLoad = incrementalLoad
403+
} else {
404+
view.wrapped.shouldIncrementalLoad = true
403405
}
404406

405407
// MaxBufferSize
@@ -413,7 +415,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
413415
// CustomLoopCount
414416
if let customLoopCount = imageConfiguration.customLoopCount {
415417
view.wrapped.shouldCustomLoopCount = true
416-
view.wrapped.animationRepeatCount = customLoopCount
418+
view.wrapped.animationRepeatCount = Int(customLoopCount)
417419
} else {
418420
// disable custom loop count
419421
view.wrapped.shouldCustomLoopCount = false
@@ -441,8 +443,8 @@ public struct AnimatedImage : PlatformViewRepresentable {
441443
}
442444

443445
// Playback Rate
444-
if let playBackRate = imageConfiguration.playBackRate {
445-
view.wrapped.playbackRate = playBackRate
446+
if let playbackRate = imageConfiguration.playbackRate {
447+
view.wrapped.playbackRate = playbackRate
446448
} else {
447449
view.wrapped.playbackRate = 1.0
448450
}
@@ -555,7 +557,7 @@ extension AnimatedImage {
555557
/// Total loop count for animated image rendering. Defaults to nil.
556558
/// - Note: Pass nil to disable customization, use the image itself loop count (`animatedImageLoopCount`) instead
557559
/// - Parameter loopCount: The animation loop count
558-
public func customLoopCount(_ loopCount: Int?) -> AnimatedImage {
560+
public func customLoopCount(_ loopCount: UInt?) -> AnimatedImage {
559561
self.imageConfiguration.customLoopCount = loopCount
560562
return self
561563
}
@@ -611,9 +613,9 @@ extension AnimatedImage {
611613
/// `0.0-1.0` means the slow speed.
612614
/// `> 1.0` means the fast speed.
613615
/// `< 0.0` is not supported currently and stop animation. (may support reverse playback in the future)
614-
/// - Parameter playBackRate: The animation playback rate.
615-
public func playBackRate(_ playBackRate: Double) -> AnimatedImage {
616-
self.imageConfiguration.playBackRate = playBackRate
616+
/// - Parameter playbackRate: The animation playback rate.
617+
public func playbackRate(_ playbackRate: Double) -> AnimatedImage {
618+
self.imageConfiguration.playbackRate = playbackRate
617619
return self
618620
}
619621
}

SDWebImageSwiftUI/Classes/WebImage.swift

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

30+
var incrementalLoad: Bool = true
31+
var maxBufferSize: UInt?
32+
var customLoopCount: UInt?
33+
var runLoopMode: RunLoop.Mode = .common
34+
var pausable: Bool = true
35+
var purgeable: Bool = false
36+
var playbackRate: Double = 1.0
37+
3038
/// Create a web image with url, placeholder, custom options and context.
3139
/// - Parameter url: The image url
3240
/// - Parameter options: The options to use when downloading the image. See `SDWebImageOptions` for the possible values.
@@ -67,7 +75,14 @@ public struct WebImage : View {
6775
self.imagePlayer?.startPlaying()
6876
}
6977
.onDisappear {
70-
self.imagePlayer?.pausePlaying()
78+
if self.pausable {
79+
self.imagePlayer?.pausePlaying()
80+
} else {
81+
self.imagePlayer?.stopPlaying()
82+
}
83+
if self.purgeable {
84+
self.imagePlayer?.clearFrameBuffer()
85+
}
7186
}
7287
} else {
7388
configurations.reduce(Image(platformImage: imageManager.image!)) { (previous, configuration) in
@@ -124,6 +139,16 @@ public struct WebImage : View {
124139
imagePlayer.animationFrameHandler = { (_, frame) in
125140
self.currentFrame = frame
126141
}
142+
// Setup configuration
143+
if let maxBufferSize = maxBufferSize {
144+
imagePlayer.maxBufferSize = maxBufferSize
145+
}
146+
if let customLoopCount = customLoopCount {
147+
imagePlayer.totalLoopCount = UInt(customLoopCount)
148+
}
149+
imagePlayer.runLoopMode = runLoopMode
150+
imagePlayer.playbackRate = playbackRate
151+
127152
self.imagePlayer = imagePlayer
128153
imagePlayer.startPlaying()
129154
}
@@ -259,6 +284,83 @@ extension WebImage {
259284
}
260285
}
261286

287+
// Animated Image
288+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
289+
extension WebImage {
290+
291+
/// Total loop count for animated image rendering. Defaults to nil.
292+
/// - Note: Pass nil to disable customization, use the image itself loop count (`animatedImageLoopCount`) instead
293+
/// - Parameter loopCount: The animation loop count
294+
public func customLoopCount(_ loopCount: UInt?) -> WebImage {
295+
var result = self
296+
result.customLoopCount = loopCount
297+
return result
298+
}
299+
300+
/// 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.
301+
///
302+
/// `0` or nil means automatically adjust by calculating current memory usage.
303+
/// `1` means without any buffer cache, each of frames will be decoded and then be freed after rendering. (Lowest Memory and Highest CPU)
304+
/// `UInt.max` means cache all the buffer. (Lowest CPU and Highest Memory)
305+
/// - Parameter bufferSize: The max buffer size
306+
public func maxBufferSize(_ bufferSize: UInt?) -> WebImage {
307+
var result = self
308+
result.maxBufferSize = bufferSize
309+
return result
310+
}
311+
312+
/// Whehter or not to enable incremental image load for animated image. See `SDAnimatedImageView` for detailed explanation for this.
313+
/// - 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.
314+
/// Default is true. Set to false to only render the static poster for incremental animated image.
315+
/// - Parameter incrementalLoad: Whether or not to incremental load
316+
public func incrementalLoad(_ incrementalLoad: Bool) -> WebImage {
317+
var result = self
318+
result.incrementalLoad = incrementalLoad
319+
return result
320+
}
321+
322+
/// The runLoopMode when animation is playing on. Defaults is `.common`
323+
/// You can specify a runloop mode to let it rendering.
324+
/// - 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)
325+
/// - Parameter runLoopMode: The runLoopMode for animation
326+
public func runLoopMode(_ runLoopMode: RunLoop.Mode) -> WebImage {
327+
var result = self
328+
result.runLoopMode = runLoopMode
329+
return result
330+
}
331+
332+
/// 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.
333+
/// - 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.
334+
/// - Parameter pausable: Whether or not to pause the animation instead of stop the animation.
335+
public func pausable(_ pausable: Bool) -> WebImage {
336+
var result = self
337+
result.pausable = pausable
338+
return result
339+
}
340+
341+
/// Whether or not to clear frame buffer cache when stopped. Defaults is false.
342+
/// 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)
343+
/// - Parameter purgeable: Whether or not to clear frame buffer cache when stopped.
344+
public func purgeable(_ purgeable: Bool) -> WebImage {
345+
var result = self
346+
result.purgeable = purgeable
347+
return result
348+
}
349+
350+
/// Control the animation playback rate. Default is 1.0.
351+
/// `1.0` means the normal speed.
352+
/// `0.0` means stopping the animation.
353+
/// `0.0-1.0` means the slow speed.
354+
/// `> 1.0` means the fast speed.
355+
/// `< 0.0` is not supported currently and stop animation. (may support reverse playback in the future)
356+
/// - Parameter playbackRate: The animation playback rate.
357+
public func playbackRate(_ playbackRate: Double) -> WebImage {
358+
var result = self
359+
result.playbackRate = playbackRate
360+
return result
361+
}
362+
}
363+
262364
#if DEBUG
263365
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
264366
struct WebImage_Previews : PreviewProvider {

0 commit comments

Comments
 (0)