From 8dc9dfc1dc0d0d25499493a0c963686b8d8d174f Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sat, 5 Oct 2019 13:53:00 +0800 Subject: [PATCH 1/3] Change the internal compatible symbol naming with Platform prefix --- SDWebImageSwiftUI/Classes/AnimatedImage.swift | 8 ++++---- SDWebImageSwiftUI/Classes/SDWebImageSwiftUI.swift | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index 60fc361..d9dbe2a 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -32,7 +32,7 @@ final class AnimatedImageLayout : ObservableObject { } // View -public struct AnimatedImage : ViewRepresentable { +public struct AnimatedImage : PlatformViewRepresentable { @ObservedObject var imageModel = AnimatedImageModel() @ObservedObject var imageLayout = AnimatedImageLayout() @@ -64,11 +64,11 @@ public struct AnimatedImage : ViewRepresentable { } #endif - func makeView(context: ViewRepresentableContext) -> AnimatedImageViewWrapper { + func makeView(context: PlatformViewRepresentableContext) -> AnimatedImageViewWrapper { AnimatedImageViewWrapper() } - func updateView(_ view: AnimatedImageViewWrapper, context: ViewRepresentableContext) { + func updateView(_ view: AnimatedImageViewWrapper, context: PlatformViewRepresentableContext) { view.wrapped.image = imageModel.image if let url = imageModel.url { view.wrapped.sd_setImage(with: url, placeholderImage: placeholder, options: webOptions, context: webContext, progress: { (receivedSize, expectedSize, _) in @@ -85,7 +85,7 @@ public struct AnimatedImage : ViewRepresentable { layoutView(view, context: context) } - func layoutView(_ view: AnimatedImageViewWrapper, context: ViewRepresentableContext) { + func layoutView(_ view: AnimatedImageViewWrapper, context: PlatformViewRepresentableContext) { // AspectRatio if let _ = imageLayout.aspectRatio { // TODO: Needs layer transform and geometry calculation diff --git a/SDWebImageSwiftUI/Classes/SDWebImageSwiftUI.swift b/SDWebImageSwiftUI/Classes/SDWebImageSwiftUI.swift index 35ff475..1f434f2 100644 --- a/SDWebImageSwiftUI/Classes/SDWebImageSwiftUI.swift +++ b/SDWebImageSwiftUI/Classes/SDWebImageSwiftUI.swift @@ -36,14 +36,14 @@ public typealias PlatformView = WKInterfaceObject #endif #if os(macOS) -typealias ViewRepresentable = NSViewRepresentable -typealias ViewRepresentableContext = NSViewRepresentableContext +typealias PlatformViewRepresentable = NSViewRepresentable +typealias PlatformViewRepresentableContext = NSViewRepresentableContext #endif #if os(iOS) || os(tvOS) -typealias ViewRepresentable = UIViewRepresentable -typealias ViewRepresentableContext = UIViewRepresentableContext +typealias PlatformViewRepresentable = UIViewRepresentable +typealias PlatformViewRepresentableContext = UIViewRepresentableContext #endif #if os(watchOS) -typealias ViewRepresentable = WKInterfaceObjectRepresentable -typealias ViewRepresentableContext = WKInterfaceObjectRepresentableContext +typealias PlatformViewRepresentable = WKInterfaceObjectRepresentable +typealias PlatformViewRepresentableContext = WKInterfaceObjectRepresentableContext #endif From d86904f2d5d27c6325af292a7accdac8983951fa Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sat, 5 Oct 2019 14:14:08 +0800 Subject: [PATCH 2/3] Add support to custom loop count / max buffer size / incremental load, which is already supported by SDAnimatedImageView --- SDWebImageSwiftUI/Classes/AnimatedImage.swift | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index d9dbe2a..89c3442 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -31,10 +31,18 @@ final class AnimatedImageLayout : ObservableObject { @Published var antialiased: Bool = false } +// Configuration Binding Object +final class AnimatedImageConfiguration: ObservableObject { + @Published var incrementalLoad: Bool? + @Published var maxBufferSize: UInt? + @Published var customLoopCount: Int? +} + // View public struct AnimatedImage : PlatformViewRepresentable { @ObservedObject var imageModel = AnimatedImageModel() @ObservedObject var imageLayout = AnimatedImageLayout() + @ObservedObject var imageConfiguration = AnimatedImageConfiguration() var placeholder: PlatformImage? var webOptions: SDWebImageOptions = [] @@ -82,6 +90,7 @@ public struct AnimatedImage : PlatformViewRepresentable { } } + configureView(view, context: context) layoutView(view, context: context) } @@ -190,6 +199,30 @@ public struct AnimatedImage : PlatformViewRepresentable { view.setNeedsDisplay() #endif } + + func configureView(_ view: AnimatedImageViewWrapper, context: PlatformViewRepresentableContext) { + // IncrementalLoad + if let incrementalLoad = imageConfiguration.incrementalLoad { + view.wrapped.shouldIncrementalLoad = incrementalLoad + } + + // MaxBufferSize + if let maxBufferSize = imageConfiguration.maxBufferSize { + view.wrapped.maxBufferSize = maxBufferSize + } else { + // automatically + view.wrapped.maxBufferSize = 0 + } + + // CustomLoopCount + if let customLoopCount = imageConfiguration.customLoopCount { + view.wrapped.shouldCustomLoopCount = true + view.wrapped.animationRepeatCount = customLoopCount + } else { + // disable custom loop count + view.wrapped.shouldCustomLoopCount = false + } + } } // Layout @@ -241,6 +274,24 @@ extension AnimatedImage { } } +// AnimatedImage Modifier +extension AnimatedImage { + public func customLoopCount(_ loopCount: Int?) -> AnimatedImage { + imageConfiguration.customLoopCount = loopCount + return self + } + + public func maxBufferSize(_ bufferSize: UInt?) -> AnimatedImage { + imageConfiguration.maxBufferSize = bufferSize + return self + } + + public func incrementalLoad(_ incrementalLoad: Bool) -> AnimatedImage { + imageConfiguration.incrementalLoad = incrementalLoad + return self + } +} + // Completion Handler extension AnimatedImage { public func onFailure(perform action: ((Error) -> Void)? = nil) -> AnimatedImage { From 7d6e2f3b5ba9b8b475f0880f3195fff0aa69dc60 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sat, 5 Oct 2019 15:02:44 +0800 Subject: [PATCH 3/3] Update the readme with the advanced control for AnimatedImage --- README.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2ef393d..a4d8e1d 100644 --- a/README.md +++ b/README.md @@ -61,11 +61,10 @@ let package = Package( ## Usage -+ Using `WebImage` to load network image +### Using `WebImage` to load network image -Supports the placeholder and detail options control for image loading as SDWebImage. - -Supports the success/failure/progress changes event for custom handling. +- [x] Supports the placeholder and detail options control for image loading as SDWebImage. +- [x] Supports the success/failure/progress changes event for custom handling. Note: Unlike `UIImageView` in UIKit, SwiftUI's `Image` does not support animation. This `WebImage` using `Image` for internal implementation and supports static image format only. @@ -81,20 +80,25 @@ var body: some View { } ``` -+ Using `AnimatedImage` to play animation +### Using `AnimatedImage` to play animation ```swift var body: some View { - AnimatedImage(url: URL(string: "https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif")) - .onFailure(perform: { (error) in - // Error - }) - .scaledToFit() - AnimatedImage(data: try! Data(contentsOf: URL(fileURLWithPath: "/tmp/foo.webp"))) - .scaledToFill() + Group { + AnimatedImage(url: URL(string: "https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif")) + .onFailure(perform: { (error) in + // Error + }) + .scaledToFit() + AnimatedImage(data: try! Data(contentsOf: URL(fileURLWithPath: "/tmp/foo.webp"))) + .customLoopCount(1) + } } ``` +- [x] Supports network image as well as local data and bundle image +- [x] Supports advanced control like loop count, incremental load, buffer size. + Note: `AnimatedImage` supports both image url or image data for animated image format. Which use the SDWebImage's [Animated ImageView](https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage#animated-image-50) for internal implementation. ## Demo