diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7a81c8f7..9706de3f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [2.2.7] - 2024-03-09
+- Fix AnimatedImage aspectRatio issue when ratio is nil #301
+- Upgrade to support visionOS on CocoaPods #298
+
+## [2.2.6] - 2023-12-13
+- Try to workaround the #281 when imagePlayer stopPlaying trigger the Combine Publisher during deallocating #287
+
+## [2.2.5] - 2023-11-29
+- Fix the AnimatedImgae rendering mode about compatible with SDWebImage 5.18+
+
+## [2.2.4] - 2023-10-21
+- Allows to use UIImage/NSImage as defaults when init the AnimatedImage with JPEG data #277
+
## [2.2.3] - 2023-04-32
- Fix the issue that Static Library + Library Evolution cause the build issue on Swift 5.8 #263
diff --git a/Example/SDWebImageSwiftUI.xcodeproj/xcshareddata/xcschemes/SDWebImageSwiftUIDemo-watchOS WatchKit App.xcscheme b/Example/SDWebImageSwiftUI.xcodeproj/xcshareddata/xcschemes/SDWebImageSwiftUIDemo-watchOS WatchKit App.xcscheme
index 3d1f081f..65df20bc 100644
--- a/Example/SDWebImageSwiftUI.xcodeproj/xcshareddata/xcschemes/SDWebImageSwiftUIDemo-watchOS WatchKit App.xcscheme
+++ b/Example/SDWebImageSwiftUI.xcodeproj/xcshareddata/xcschemes/SDWebImageSwiftUIDemo-watchOS WatchKit App.xcscheme
@@ -54,10 +54,8 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
-
+
-
+
-
+
-
-
-
-
-
+
diff --git a/README.md b/README.md
index d64f3c3f..eb76b17e 100644
--- a/README.md
+++ b/README.md
@@ -55,6 +55,7 @@ All issue reports, feature requests, contributions, and GitHub stars are welcome
+ macOS 10.15+ (11+ Recommended)
+ tvOS 13+ (14+ Recommended)
+ watchOS 6+ (7+ Recommended)
++ visionOS 1+
## SwiftUI 2.0 Compatibility
@@ -229,7 +230,7 @@ Note: `AnimatedImage` supports both image url or image data for animated image f
Note: `AnimatedImage` some methods like `.transition`, `.indicator` and `.aspectRatio` have the same naming as `SwiftUI.View` protocol methods. But the args receive the different type. This is because `AnimatedImage` supports to be used with UIKit/AppKit component and animation. If you find ambiguity, use full type declaration instead of the dot expression syntax.
-Note: some of methods on `AnimatedImage` will return `some View`, a new Modified Content. You'll lose the type related modifier method. For this case, you can either reorder the method call, or use Native View in `.onViewUpdate` for rescue.
+Note: some of methods on `AnimatedImage` will return `some View`, a new Modified Content. You'll lose the type related modifier method. For this case, you can either reorder the method call, or use native view (actually `SDAnimatedImageView`) in `.onViewUpdate`, use UIKIt/AppKit API for rescue.
```swift
@@ -324,7 +325,7 @@ For more information, it's really recommended to check our demo, to learn detail
## Documentation
-+ [SDWebImageSwiftUI API documentation](https://sdwebimage.github.io/SDWebImageSwiftUI/)
++ [SDWebImageSwiftUI API documentation](https://sdwebimage.github.io/documentation/sdwebimageswiftui/)
+ [SDWebImage API documentation](https://sdwebimage.github.io/)
## FAQ
@@ -417,6 +418,42 @@ NavigationView {
}
```
+#### Render vector image (SVG/PDF) with tint color
+
+Both `WebImage/AnimatedImage` supports to render the vector image, by using the `SVG/PDF` external coders. However they are different internally.
+
++ `AnimatedImage`: use tech from Apple's symbol image and vector drawing, supports dynamic size changes without lossing details. And it use UIKit/AppKit based implementation and APIs. If you want, pass `.context(.imageThumbnailPixelSize: size)` to use bitmap rendering and get more pixels.
++ `WebImage`: draws vector image into a bitmap version. Which just like normal PNG. By default, we use vector image content size (SVG canvas size or PDF media box size). If you want, pass `.context(.imageThumbnailPixelSize: size)` to get more pixels.
+
+For bitmap rendering, you can also tint the SVG/PDF icons with custom colors (like symbol images), use the `.renderingMode(.template)` and `.tint(:)` or `.foregroundColor(:)` modifier, which matches `SwiftUI.Image` behavior.
+
++ WebImage
+
+```swift
+var body: some View {
+ WebImage(url: URL(string: "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/w3c.svg"))
+ .resizable()
+ .renderingMode(.template)
+ .foregroundColor(.red) // or `.tint(:)`, `.accentColor(:)`
+ .scaledToFit()
+}
+```
+
++ AnimatedImage
+
+```swift
+var body: some View {
+ AnimatedImage(url: URL(string: "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/w3c.svg"), context: [.imageThumbnailPixelSize : CGSize(width: 100, height: 100)])
+ .resizable()
+ .renderingMode(.template)
+ // seems `.foregroundColor(:)` does effect `UIView.tintColor`, use `tint(:)` or `.accentColor(:)` instead.
+ // Or you can use `onViewCreate(:)` to get native `SDAnimatedImageView` and set `tintColor` (AppKit use `contentTintColor`)
+ .tint(.red)
+ .scaledToFit()
+}
+```
+
+See more: [Configuring and displaying symbol images in your UI](https://developer.apple.com/documentation/uikit/uiimage/configuring_and_displaying_symbol_images_in_your_ui?language=objc)
#### Using with external loaders/caches/coders
diff --git a/SDWebImageSwiftUI.podspec b/SDWebImageSwiftUI.podspec
index 0c83570e..58ddaf2a 100644
--- a/SDWebImageSwiftUI.podspec
+++ b/SDWebImageSwiftUI.podspec
@@ -8,7 +8,7 @@
Pod::Spec.new do |s|
s.name = 'SDWebImageSwiftUI'
- s.version = '2.2.3'
+ s.version = '2.2.7'
s.summary = 'SwiftUI Image loading and Animation framework powered by SDWebImage'
s.description = <<-DESC
@@ -25,6 +25,7 @@ It brings all your favorite features from SDWebImage, like async image loading,
s.osx.deployment_target = '10.15'
s.tvos.deployment_target = '13.0'
s.watchos.deployment_target = '6.0'
+ s.visionos.deployment_target = '1.0'
s.source_files = 'SDWebImageSwiftUI/Classes/**/*', 'SDWebImageSwiftUI/Module/*.h'
s.pod_target_xcconfig = {
diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift
index e454432f..49ce8f85 100644
--- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift
+++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift
@@ -301,15 +301,29 @@ public struct AnimatedImage : PlatformViewRepresentable {
// Refresh image, imageModel is the Source of Truth, switch the type
// Although we have Source of Truth, we can check the previous value, to avoid re-generate SDAnimatedImage, which is performance-cost.
if let name = imageModel.name, name != context.coordinator.imageLoading.imageName {
+ var image: PlatformImage?
#if os(macOS)
- let image = SDAnimatedImage(named: name, in: imageModel.bundle)
+ image = SDAnimatedImage(named: name, in: imageModel.bundle)
+ if image == nil {
+ // For static image, use NSImage as defaults
+ let bundle = imageModel.bundle ?? .main
+ image = bundle.image(forResource: name)
+ }
#else
- let image = SDAnimatedImage(named: name, in: imageModel.bundle, compatibleWith: nil)
+ image = SDAnimatedImage(named: name, in: imageModel.bundle, compatibleWith: nil)
+ if image == nil {
+ // For static image, use UIImage as defaults
+ image = PlatformImage(named: name, in: imageModel.bundle, compatibleWith: nil)
+ }
#endif
context.coordinator.imageLoading.imageName = name
view.wrapped.image = image
} else if let data = imageModel.data, data != context.coordinator.imageLoading.imageData {
- let image = SDAnimatedImage(data: data, scale: imageModel.scale)
+ var image: PlatformImage? = SDAnimatedImage(data: data, scale: imageModel.scale)
+ if image == nil {
+ // For static image, use UIImage as defaults
+ image = PlatformImage.sd_image(with: data, scale: imageModel.scale)
+ }
context.coordinator.imageLoading.imageData = data
view.wrapped.image = image
} else if let url = imageModel.url {
@@ -422,7 +436,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
}
// Animated Image does not support resizing mode and rendering mode
- if let image = view.wrapped.image, !image.conforms(to: SDAnimatedImageProtocol.self) {
+ if let image = view.wrapped.image {
var image = image
// ResizingMode
if let resizingMode = imageLayout.resizingMode, imageLayout.capInsets != EdgeInsets() {
@@ -608,6 +622,11 @@ extension AnimatedImage {
// Aspect Ratio
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension AnimatedImage {
+ func setImageLayoutAspectRatio(_ aspectRatio: CGFloat?, contentMode: ContentMode) {
+ self.imageLayout.aspectRatio = aspectRatio
+ self.imageLayout.contentMode = contentMode
+ }
+
/// Constrains this view's dimensions to the specified aspect ratio.
/// - Parameters:
/// - aspectRatio: The ratio of width to height to use for the resulting
@@ -617,6 +636,7 @@ extension AnimatedImage {
/// fill the parent context.
/// - Returns: A view that constrains this view's dimensions to
/// `aspectRatio`, using `contentMode` as its scaling algorithm.
+ @ViewBuilder
public func aspectRatio(_ aspectRatio: CGFloat? = nil, contentMode: ContentMode) -> some View {
// The `SwifUI.View.aspectRatio(_:contentMode:)` says:
// If `aspectRatio` is `nil`, the resulting view maintains this view's aspect ratio
@@ -626,9 +646,12 @@ extension AnimatedImage {
// But 2: there are no way to call a Protocol Extention default implementation in Swift 5.1
// So, we directly call the implementation detail modifier instead
// Fired Radar: FB7413534
- self.imageLayout.aspectRatio = aspectRatio
- self.imageLayout.contentMode = contentMode
- return self.modifier(_AspectRatioLayout(aspectRatio: aspectRatio, contentMode: contentMode))
+ let _ = self.setImageLayoutAspectRatio(aspectRatio, contentMode: contentMode)
+ if let aspectRatio {
+ self.modifier(_AspectRatioLayout(aspectRatio: aspectRatio, contentMode: contentMode))
+ } else {
+ self
+ }
}
/// Constrains this view's dimensions to the aspect ratio of the given size.
diff --git a/SDWebImageSwiftUI/Classes/ImageManager.swift b/SDWebImageSwiftUI/Classes/ImageManager.swift
index d9bce8fa..668fb3b3 100644
--- a/SDWebImageSwiftUI/Classes/ImageManager.swift
+++ b/SDWebImageSwiftUI/Classes/ImageManager.swift
@@ -7,6 +7,7 @@
*/
import SwiftUI
+import Combine
import SDWebImage
/// A Image observable object for handle image load process. This drive the Source of Truth for image loading status.
diff --git a/SDWebImageSwiftUI/Classes/ImagePlayer.swift b/SDWebImageSwiftUI/Classes/ImagePlayer.swift
index 4e61e820..0ba09fc5 100644
--- a/SDWebImageSwiftUI/Classes/ImagePlayer.swift
+++ b/SDWebImageSwiftUI/Classes/ImagePlayer.swift
@@ -7,6 +7,7 @@
*/
import SwiftUI
+import Combine
import SDWebImage
/// A Image observable object for handle aniamted image playback. This is used to avoid `@State` update may capture the View struct type and cause memory leak.
@@ -29,10 +30,6 @@ public final class ImagePlayer : ObservableObject {
/// Animation playback mode
public var playbackMode: SDAnimatedImagePlaybackMode = .normal
- deinit {
- player?.stopPlaying()
- }
-
/// Current playing frame image
@Published public var currentFrame: PlatformImage?
diff --git a/SDWebImageSwiftUI/Classes/Indicator/Indicator.swift b/SDWebImageSwiftUI/Classes/Indicator/Indicator.swift
index 37eb9030..3461b082 100644
--- a/SDWebImageSwiftUI/Classes/Indicator/Indicator.swift
+++ b/SDWebImageSwiftUI/Classes/Indicator/Indicator.swift
@@ -7,6 +7,7 @@
*/
import Foundation
+import Combine
import SwiftUI
/// A type to build the indicator
diff --git a/SDWebImageSwiftUI/Module/Info.plist b/SDWebImageSwiftUI/Module/Info.plist
index 49c664c0..24336cf6 100644
--- a/SDWebImageSwiftUI/Module/Info.plist
+++ b/SDWebImageSwiftUI/Module/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
$(PRODUCT_BUNDLE_PACKAGE_TYPE)
CFBundleShortVersionString
- 2.2.3
+ 2.2.7
CFBundleVersion
$(CURRENT_PROJECT_VERSION)