diff --git a/Package.swift b/Package.swift index e7c307f..7e53f13 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.2 +// swift-tools-version:5.3 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "SDWebImageSwiftUI", platforms: [ - .macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6) + .macOS(.v11), .iOS(.v14), .tvOS(.v14), .watchOS(.v7) ], products: [ // Products define the executables and libraries produced by a package, and make them visible to other packages. diff --git a/README.md b/README.md index d64f3c3..4f40528 100644 --- a/README.md +++ b/README.md @@ -51,10 +51,10 @@ All issue reports, feature requests, contributions, and GitHub stars are welcome ## Requirements + Xcode 12+ -+ iOS 13+ (14+ Recommended) -+ macOS 10.15+ (11+ Recommended) -+ tvOS 13+ (14+ Recommended) -+ watchOS 6+ (7+ Recommended) ++ iOS 14+ ++ macOS 11+ ++ tvOS 14+ ++ watchOS 7+ ## SwiftUI 2.0 Compatibility @@ -74,9 +74,7 @@ var body: some View { } ``` -Note: However, many differences behavior between iOS 13/14's is hard to fixup. And we may break some APIs (which are not designed to be public) to fixup it. - -Due to maintain issue, in the future release, we will drop the iOS 13 supports and always match SwiftUI 2.0's behavior. And **v2.x** may be the last version support iOS 13. +Note: However, many differences behavior between iOS 13/14 is hard to fixup. Due to maintain issue, from SDWebImageSwiftUI v3.0, iOS 13 is no longer supported. We always match SwiftUI 2.0's behavior. ## Installation @@ -514,7 +512,7 @@ For caches, you actually don't need to worry about anything. It just works after #### Using for backward deployment and weak linking SwiftUI -SDWebImageSwiftUI supports to use when your App Target has a deployment target version less than iOS 13/macOS 10.15/tvOS 13/watchOS 6. Which will weak linking of SwiftUI(Combine) to allows writing code with available check at runtime. +SDWebImageSwiftUI supports to use when your App Target has a deployment target version less than iOS 14/macOS 11/tvOS 14/watchOS 7. Which will weak linking of SwiftUI(Combine) to allows writing code with available check at runtime. To use backward deployment, you have to do the follow things: @@ -528,7 +526,7 @@ You should notice that all the third party SwiftUI frameworks should have this b For deployment target version below iOS 12.2 (The first version which Swift 5 Runtime bundled in iOS system), you have to change the min deployment target version of SDWebImageSwiftUI. This may take some side effect on compiler's optimization and trigger massive warnings for some frameworks. -However, for iOS 12.2+, you can still keep the min deployment target version to iOS 13, no extra warnings or performance slow down for iOS 13 client. +However, for iOS 12.2+, you can still keep the min deployment target version to iOS 14, no extra warnings or performance slow down for iOS 14 client. Because Swift use the min deployment target version to detect whether to link the App bundled Swift runtime, or the System built-in one (`/usr/lib/swift/libswiftCore.dylib`). @@ -555,7 +553,7 @@ end + For CocoaPods user, you can skip the platform version validation in Podfile with: ```ruby -platform :ios, '13.0' # This does not effect your App Target's deployment target version, just a hint for CocoaPods +platform :ios, '14.0' # This does not effect your App Target's deployment target version, just a hint for CocoaPods ``` + For SwiftPM user, SwiftPM does not support weak linking nor Library Evolution, so it can not deployment to iOS 12+ user without changing the min deployment target. @@ -568,7 +566,7 @@ Add **all the SwiftUI code** with the available annotation and runtime check, li // AppDelegate.swift func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // ... - if #available(iOS 13, *) { + if #available(iOS 14, *) { window.rootViewController = UIHostingController(rootView: ContentView()) } else { window.rootViewController = ViewController() @@ -590,11 +588,11 @@ class ViewController: UIViewController { } // ContentView.swift -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) struct ContentView : View { var body: some View { Group { - Text("Hello World iOS 13!") + Text("Hello World iOS 14!") WebImage(url: URL(string: "https://i.loli.net/2019/09/24/rX2RkVWeGKIuJvc.jpg")) } } diff --git a/SDWebImageSwiftUI.podspec b/SDWebImageSwiftUI.podspec index 1562601..38566a0 100644 --- a/SDWebImageSwiftUI.podspec +++ b/SDWebImageSwiftUI.podspec @@ -21,10 +21,10 @@ It brings all your favorite features from SDWebImage, like async image loading, s.author = { 'DreamPiggy' => 'lizhuoli1126@126.com' } s.source = { :git => 'https://github.com/SDWebImage/SDWebImageSwiftUI.git', :tag => s.version.to_s } - s.ios.deployment_target = '13.0' - s.osx.deployment_target = '10.15' - s.tvos.deployment_target = '13.0' - s.watchos.deployment_target = '6.0' + s.ios.deployment_target = '14.0' + s.osx.deployment_target = '11.0' + s.tvos.deployment_target = '14.0' + s.watchos.deployment_target = '7.0' s.source_files = 'SDWebImageSwiftUI/Classes/**/*', 'SDWebImageSwiftUI/Module/*.h' s.pod_target_xcconfig = { @@ -35,5 +35,5 @@ It brings all your favorite features from SDWebImage, like async image loading, s.weak_frameworks = 'SwiftUI', 'Combine' s.dependency 'SDWebImage', '~> 5.10' - s.swift_version = '5.2' + s.swift_version = '5.3' end diff --git a/SDWebImageSwiftUI.xcodeproj/project.pbxproj b/SDWebImageSwiftUI.xcodeproj/project.pbxproj index 1fbde81..5d05341 100644 --- a/SDWebImageSwiftUI.xcodeproj/project.pbxproj +++ b/SDWebImageSwiftUI.xcodeproj/project.pbxproj @@ -31,22 +31,6 @@ 32B933E623659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; }; 32B933E723659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; }; 32B933E823659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; }; - 32BC087328D23D35002451BD /* StateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC086F28D23D35002451BD /* StateObject.swift */; }; - 32BC087428D23D35002451BD /* StateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC086F28D23D35002451BD /* StateObject.swift */; }; - 32BC087528D23D35002451BD /* StateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC086F28D23D35002451BD /* StateObject.swift */; }; - 32BC087628D23D35002451BD /* StateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC086F28D23D35002451BD /* StateObject.swift */; }; - 32BC087728D23D35002451BD /* OnChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087028D23D35002451BD /* OnChange.swift */; }; - 32BC087828D23D35002451BD /* OnChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087028D23D35002451BD /* OnChange.swift */; }; - 32BC087928D23D35002451BD /* OnChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087028D23D35002451BD /* OnChange.swift */; }; - 32BC087A28D23D35002451BD /* OnChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087028D23D35002451BD /* OnChange.swift */; }; - 32BC087B28D23D35002451BD /* Overlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087128D23D35002451BD /* Overlay.swift */; }; - 32BC087C28D23D35002451BD /* Overlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087128D23D35002451BD /* Overlay.swift */; }; - 32BC087D28D23D35002451BD /* Overlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087128D23D35002451BD /* Overlay.swift */; }; - 32BC087E28D23D35002451BD /* Overlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087128D23D35002451BD /* Overlay.swift */; }; - 32BC087F28D23D35002451BD /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087228D23D35002451BD /* Backport.swift */; }; - 32BC088028D23D35002451BD /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087228D23D35002451BD /* Backport.swift */; }; - 32BC088128D23D35002451BD /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087228D23D35002451BD /* Backport.swift */; }; - 32BC088228D23D35002451BD /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087228D23D35002451BD /* Backport.swift */; }; 32C43DE622FD54CD00BE87F5 /* SDWebImageSwiftUI.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C43DE422FD54CD00BE87F5 /* SDWebImageSwiftUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32C43DEA22FD577300BE87F5 /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32C43DE922FD577300BE87F5 /* SDWebImage.framework */; }; 32C43E1622FD583700BE87F5 /* ImageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43DDC22FD54C600BE87F5 /* ImageManager.swift */; }; @@ -93,10 +77,6 @@ 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewWrapper.swift; sourceTree = ""; }; 32B79C9428DB40430088C432 /* SwiftUICompatibility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftUICompatibility.swift; sourceTree = ""; }; 32B933E423659A1900BB7CAD /* Transition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Transition.swift; sourceTree = ""; }; - 32BC086F28D23D35002451BD /* StateObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateObject.swift; sourceTree = ""; }; - 32BC087028D23D35002451BD /* OnChange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnChange.swift; sourceTree = ""; }; - 32BC087128D23D35002451BD /* Overlay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Overlay.swift; sourceTree = ""; }; - 32BC087228D23D35002451BD /* Backport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Backport.swift; sourceTree = ""; }; 32BD9C4623E03B08008D5F6A /* IndicatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndicatorTests.swift; sourceTree = ""; }; 32C43DCC22FD540D00BE87F5 /* SDWebImageSwiftUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImageSwiftUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 32C43DDC22FD54C600BE87F5 /* ImageManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageManager.swift; sourceTree = ""; }; @@ -185,17 +165,6 @@ path = Transition; sourceTree = ""; }; - 32BC086E28D23D35002451BD /* Backports */ = { - isa = PBXGroup; - children = ( - 32BC086F28D23D35002451BD /* StateObject.swift */, - 32BC087028D23D35002451BD /* OnChange.swift */, - 32BC087128D23D35002451BD /* Overlay.swift */, - 32BC087228D23D35002451BD /* Backport.swift */, - ); - path = Backports; - sourceTree = ""; - }; 32C43DC222FD540D00BE87F5 = { isa = PBXGroup; children = ( @@ -232,7 +201,6 @@ children = ( 32B933E323659A0700BB7CAD /* Transition */, 326099472362E09E006EBB22 /* Indicator */, - 32BC086E28D23D35002451BD /* Backports */, 32C43DDC22FD54C600BE87F5 /* ImageManager.swift */, 32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */, 32C43DDE22FD54C600BE87F5 /* WebImage.swift */, @@ -453,11 +421,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 32BC087328D23D35002451BD /* StateObject.swift in Sources */, - 32BC087728D23D35002451BD /* OnChange.swift in Sources */, 32B933E523659A1900BB7CAD /* Transition.swift in Sources */, 32CBA78025E4D7D800C6A8DC /* ImagePlayer.swift in Sources */, - 32BC087B28D23D35002451BD /* Overlay.swift in Sources */, 32C43E1722FD583700BE87F5 /* WebImage.swift in Sources */, 326B848C236335400011BDFB /* ProgressIndicator.swift in Sources */, 326B84822363350C0011BDFB /* Indicator.swift in Sources */, @@ -468,7 +433,6 @@ 32C43E1622FD583700BE87F5 /* ImageManager.swift in Sources */, 32C43E1822FD583700BE87F5 /* AnimatedImage.swift in Sources */, 32D26A022446B546005905DA /* Image.swift in Sources */, - 32BC087F28D23D35002451BD /* Backport.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -476,11 +440,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 32BC087428D23D35002451BD /* StateObject.swift in Sources */, - 32BC087828D23D35002451BD /* OnChange.swift in Sources */, 32B933E623659A1900BB7CAD /* Transition.swift in Sources */, 32CBA78125E4D7D800C6A8DC /* ImagePlayer.swift in Sources */, - 32BC087C28D23D35002451BD /* Overlay.swift in Sources */, 32C43E1A22FD583700BE87F5 /* WebImage.swift in Sources */, 326B848D236335400011BDFB /* ProgressIndicator.swift in Sources */, 326B84832363350C0011BDFB /* Indicator.swift in Sources */, @@ -491,7 +452,6 @@ 32C43E1922FD583700BE87F5 /* ImageManager.swift in Sources */, 32C43E1B22FD583700BE87F5 /* AnimatedImage.swift in Sources */, 32D26A032446B546005905DA /* Image.swift in Sources */, - 32BC088028D23D35002451BD /* Backport.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -499,11 +459,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 32BC087528D23D35002451BD /* StateObject.swift in Sources */, - 32BC087928D23D35002451BD /* OnChange.swift in Sources */, 32B933E723659A1900BB7CAD /* Transition.swift in Sources */, 32CBA78225E4D7D800C6A8DC /* ImagePlayer.swift in Sources */, - 32BC087D28D23D35002451BD /* Overlay.swift in Sources */, 32C43E1D22FD583800BE87F5 /* WebImage.swift in Sources */, 326B848E236335400011BDFB /* ProgressIndicator.swift in Sources */, 326B84842363350C0011BDFB /* Indicator.swift in Sources */, @@ -514,7 +471,6 @@ 32C43E1C22FD583800BE87F5 /* ImageManager.swift in Sources */, 32C43E1E22FD583800BE87F5 /* AnimatedImage.swift in Sources */, 32D26A042446B546005905DA /* Image.swift in Sources */, - 32BC088128D23D35002451BD /* Backport.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -522,11 +478,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 32BC087628D23D35002451BD /* StateObject.swift in Sources */, - 32BC087A28D23D35002451BD /* OnChange.swift in Sources */, 32B933E823659A1900BB7CAD /* Transition.swift in Sources */, 32CBA78325E4D7D800C6A8DC /* ImagePlayer.swift in Sources */, - 32BC087E28D23D35002451BD /* Overlay.swift in Sources */, 32C43E2022FD583800BE87F5 /* WebImage.swift in Sources */, 326B848F236335400011BDFB /* ProgressIndicator.swift in Sources */, 326B84852363350C0011BDFB /* Indicator.swift in Sources */, @@ -537,7 +490,6 @@ 32C43E1F22FD583800BE87F5 /* ImageManager.swift in Sources */, 32C43E2122FD583800BE87F5 /* AnimatedImage.swift in Sources */, 32D26A052446B546005905DA /* Image.swift in Sources */, - 32BC088228D23D35002451BD /* Backport.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -596,8 +548,8 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MACOSX_DEPLOYMENT_TARGET = 10.15; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MACOSX_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -610,10 +562,10 @@ SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TVOS_DEPLOYMENT_TARGET = 13.0; + TVOS_DEPLOYMENT_TARGET = 14.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 6.0; + WATCHOS_DEPLOYMENT_TARGET = 7.0; }; name = Debug; }; @@ -663,8 +615,8 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MACOSX_DEPLOYMENT_TARGET = 10.15; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MACOSX_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; OTHER_LDFLAGS = ( @@ -676,11 +628,11 @@ SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; - TVOS_DEPLOYMENT_TARGET = 13.0; + TVOS_DEPLOYMENT_TARGET = 14.0; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 6.0; + WATCHOS_DEPLOYMENT_TARGET = 7.0; }; name = Release; }; @@ -764,7 +716,6 @@ "@executable_path/../Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUI-macOS"; PRODUCT_NAME = SDWebImageSwiftUI; SDKROOT = macosx; @@ -795,7 +746,6 @@ "@executable_path/../Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUI-macOS"; PRODUCT_NAME = SDWebImageSwiftUI; SDKROOT = macosx; diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index e454432..2835775 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -12,7 +12,7 @@ import SDWebImage #if os(iOS) || os(tvOS) || os(macOS) /// A coordinator object used for `AnimatedImage`native view bridge for UIKit/AppKit. -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public final class AnimatedImageCoordinator: NSObject { /// Any user-provided object for actual coordinator, such as delegate method, taget-action @@ -25,7 +25,7 @@ public final class AnimatedImageCoordinator: NSObject { } /// Data Binding Object, only properties in this object can support changes from user with @State and refresh -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) final class AnimatedImageModel : ObservableObject { /// URL image @Published var url: URL? @@ -40,7 +40,7 @@ final class AnimatedImageModel : ObservableObject { } /// Loading Binding Object, only properties in this object can support changes from user with @State and refresh -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) final class AnimatedLoadingModel : ObservableObject { @Published var image: PlatformImage? // loaded image, note when progressive loading, this will published multiple times with different partial image @Published var isLoading: Bool = false // whether network is loading or cache is querying, should only be used for indicator binding @@ -53,7 +53,7 @@ final class AnimatedLoadingModel : ObservableObject { } /// Completion Handler Binding Object, supports dynamic @State changes -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) final class AnimatedImageHandler: ObservableObject { // Completion Handler @Published var successBlock: ((PlatformImage, Data?, SDImageCacheType) -> Void)? @@ -65,7 +65,7 @@ final class AnimatedImageHandler: ObservableObject { } /// Layout Binding Object, supports dynamic @State changes -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) final class AnimatedImageLayout : ObservableObject { var contentMode: ContentMode? var aspectRatio: CGFloat? @@ -77,7 +77,7 @@ final class AnimatedImageLayout : ObservableObject { } /// Configuration Binding Object, supports dynamic @State changes -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) final class AnimatedImageConfiguration: ObservableObject { var incrementalLoad: Bool? var maxBufferSize: UInt? @@ -99,7 +99,7 @@ final class AnimatedImageConfiguration: ObservableObject { } /// A Image View type to load image from url, data or bundle. Supports animated and static image format. -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public struct AnimatedImage : PlatformViewRepresentable { @ObservedObject var imageModel: AnimatedImageModel @ObservedObject var imageHandler = AnimatedImageHandler() @@ -566,7 +566,7 @@ public struct AnimatedImage : PlatformViewRepresentable { } // Layout -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension AnimatedImage { /// Configurate this view's image with the specified cap insets and options. @@ -606,7 +606,7 @@ extension AnimatedImage { } // Aspect Ratio -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension AnimatedImage { /// Constrains this view's dimensions to the specified aspect ratio. /// - Parameters: @@ -659,7 +659,7 @@ extension AnimatedImage { } // AnimatedImage Modifier -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension AnimatedImage { /// Total loop count for animated image rendering. Defaults to nil. @@ -736,7 +736,7 @@ extension AnimatedImage { } // Completion Handler -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension AnimatedImage { /// Provide the action when image load fails. @@ -768,7 +768,7 @@ extension AnimatedImage { } // View Coordinator Handler -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension AnimatedImage { /// Provide the action when view representable create the native view. @@ -796,7 +796,7 @@ extension AnimatedImage { } // Web Image convenience, based on UIKit/AppKit API -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension AnimatedImage { /// Associate a placeholder when loading image with url @@ -837,7 +837,7 @@ extension AnimatedImage { } // Indicator -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension AnimatedImage { /// Associate a indicator when loading image with url @@ -854,7 +854,7 @@ extension AnimatedImage { } #if DEBUG -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) struct AnimatedImage_Previews : PreviewProvider { static var previews: some View { Group { diff --git a/SDWebImageSwiftUI/Classes/Backports/Backport.swift b/SDWebImageSwiftUI/Classes/Backports/Backport.swift deleted file mode 100644 index 5b0c5a4..0000000 --- a/SDWebImageSwiftUI/Classes/Backports/Backport.swift +++ /dev/null @@ -1,59 +0,0 @@ -import SwiftUI -import ObjectiveC - -/// Provides a convenient method for backporting API, -/// including types, functions, properties, property wrappers and more. -/// -/// To backport a SwiftUI Label for example, you could apply the -/// following extension: -/// -/// extension Backport where Content == Any { -/// public struct Label { } -/// } -/// -/// Now if we want to provide further extensions to our backport type, -/// we need to ensure we retain the `Content == Any` generic requirement: -/// -/// extension Backport.Label where Content == Any, Title == Text, Icon == Image { -/// public init(_ title: S, systemName: String) { } -/// } -/// -/// In addition to types, we can also provide backports for properties -/// and methods: -/// -/// extension Backport.Label where Content: View { -/// func onChange(of value: Value, perform action: (Value) -> Void) -> some View { -/// // `content` provides access to the extended type -/// content.modifier(OnChangeModifier(value, action)) -/// } -/// } -/// -public struct Backport { - - /// The underlying content this backport represents. - public let content: Wrapped - - /// Initializes a new Backport for the specified content. - /// - Parameter content: The content (type) that's being backported - public init(_ content: Wrapped) { - self.content = content - } - -} - -public extension View { - /// Wraps a SwiftUI `View` that can be extended to provide backport functionality. - var backport: Backport { .init(self) } -} - -public extension NSObjectProtocol { - /// Wraps an `NSObject` that can be extended to provide backport functionality. - var backport: Backport { .init(self) } -} - -public extension AnyTransition { - /// Wraps an `AnyTransition` that can be extended to provide backport functionality. - static var backport: Backport{ - Backport(.identity) - } -} diff --git a/SDWebImageSwiftUI/Classes/Backports/OnChange.swift b/SDWebImageSwiftUI/Classes/Backports/OnChange.swift deleted file mode 100644 index c53eaf7..0000000 --- a/SDWebImageSwiftUI/Classes/Backports/OnChange.swift +++ /dev/null @@ -1,52 +0,0 @@ -import SwiftUI -import Combine - -@available(iOS, deprecated: 14.0) -@available(macOS, deprecated: 11.0) -@available(tvOS, deprecated: 14.0) -@available(watchOS, deprecated: 7.0) -public extension Backport where Wrapped: View { - - /// Adds a modifier for this view that fires an action when a specific - /// value changes. - /// - /// `onChange` is called on the main thread. Avoid performing long-running - /// tasks on the main thread. If you need to perform a long-running task in - /// response to `value` changing, you should dispatch to a background queue. - /// - /// The new value is passed into the closure. - /// - /// - Parameters: - /// - value: The value to observe for changes - /// - action: A closure to run when the value changes. - /// - newValue: The new value that changed - /// - /// - Returns: A view that fires an action when the specified value changes. - @ViewBuilder - func onChange(of value: Value, perform action: @escaping (Value) -> Void) -> some View { - content.modifier(ChangeModifier(value: value, action: action)) - } - -} - -private struct ChangeModifier: ViewModifier { - let value: Value - let action: (Value) -> Void - - @State var oldValue: Value? - - init(value: Value, action: @escaping (Value) -> Void) { - self.value = value - self.action = action - _oldValue = .init(initialValue: value) - } - - func body(content: Content) -> some View { - content - .onReceive(Just(value)) { newValue in - guard newValue != oldValue else { return } - action(newValue) - oldValue = newValue - } - } -} diff --git a/SDWebImageSwiftUI/Classes/Backports/Overlay.swift b/SDWebImageSwiftUI/Classes/Backports/Overlay.swift deleted file mode 100644 index a6f1a1f..0000000 --- a/SDWebImageSwiftUI/Classes/Backports/Overlay.swift +++ /dev/null @@ -1,124 +0,0 @@ -import SwiftUI - -public extension Backport where Wrapped: View { - - /// Layers the views that you specify in front of this view. - /// - /// Use this modifier to place one or more views in front of another view. - /// For example, you can place a group of stars on a ``RoundedRectangle``: - /// - /// RoundedRectangle(cornerRadius: 8) - /// .frame(width: 200, height: 100) - /// .overlay(alignment: .topLeading) { Star(color: .red) } - /// .overlay(alignment: .topTrailing) { Star(color: .yellow) } - /// .overlay(alignment: .bottomLeading) { Star(color: .green) } - /// .overlay(alignment: .bottomTrailing) { Star(color: .blue) } - /// - /// The example above assumes that you've defined a `Star` view with a - /// parameterized color: - /// - /// struct Star: View { - /// var color = Color.yellow - /// - /// var body: some View { - /// Image(systemName: "star.fill") - /// .foregroundStyle(color) - /// } - /// } - /// - /// By setting different `alignment` values for each modifier, you make the - /// stars appear in different places on the rectangle: - /// - /// ![A screenshot of a rounded rectangle with a star in each corner. The - /// star in the upper-left is red; the start in the upper-right is yellow; - /// the star in the lower-left is green; the star the lower-right is - /// blue.](View-overlay-2) - /// - /// If you specify more than one view in the `content` closure, the modifier - /// collects all of the views in the closure into an implicit ``ZStack``, - /// taking them in order from back to front. For example, you can place a - /// star and a ``Circle`` on a field of ``ShapeStyle/blue``: - /// - /// Color.blue - /// .frame(width: 200, height: 200) - /// .overlay { - /// Circle() - /// .frame(width: 100, height: 100) - /// Star() - /// } - /// - /// Both the overlay modifier and the implicit ``ZStack`` composed from the - /// overlay content --- the circle and the star --- use a default - /// ``Alignment/center`` alignment. The star appears centered on the circle, - /// and both appear as a composite view centered in front of the square: - /// - /// ![A screenshot of a star centered on a circle, which is - /// centered on a square.](View-overlay-3) - /// - /// If you specify an alignment for the overlay, it applies to the implicit - /// stack rather than to the individual views in the closure. You can see - /// this if you add the ``Alignment/bottom`` alignment: - /// - /// Color.blue - /// .frame(width: 200, height: 200) - /// .overlay(alignment: .bottom) { - /// Circle() - /// .frame(width: 100, height: 100) - /// Star() - /// } - /// - /// The circle and the star move down as a unit to align the stack's bottom - /// edge with the bottom edge of the square, while the star remains - /// centered on the circle: - /// - /// ![A screenshot of a star centered on a circle, which is on a square. - /// The circle's bottom edge is aligned with the square's bottom - /// edge.](View-overlay-3a) - /// - /// To control the placement of individual items inside the `content` - /// closure, either use a different overlay modifier for each item, as the - /// earlier example of stars in the corners of a rectangle demonstrates, or - /// add an explicit ``ZStack`` inside the content closure with its own - /// alignment: - /// - /// Color.blue - /// .frame(width: 200, height: 200) - /// .overlay(alignment: .bottom) { - /// ZStack(alignment: .bottom) { - /// Circle() - /// .frame(width: 100, height: 100) - /// Star() - /// } - /// } - /// - /// The stack alignment ensures that the star's bottom edge aligns with the - /// circle's, while the overlay aligns the composite view with the square: - /// - /// ![A screenshot of a star, a circle, and a square with all their - /// bottom edges aligned.](View-overlay-4) - /// - /// You can achieve layering without an overlay modifier by putting both the - /// modified view and the overlay content into a ``ZStack``. This can - /// produce a simpler view hierarchy, but changes the layout priority that - /// SwiftUI applies to the views. Use the overlay modifier when you want the - /// modified view to dominate the layout. - /// - /// If you want to specify a ``ShapeStyle`` like a ``Color`` or a - /// ``Material`` as the overlay, use - /// ``View/overlay(_:ignoresSafeAreaEdges:)`` instead. To specify a - /// ``Shape``, use ``View/overlay(_:in:fillStyle:)``. - /// - /// - Parameters: - /// - alignment: The alignment that the modifier uses to position the - /// implicit ``ZStack`` that groups the foreground views. The default - /// is ``Alignment/center``. - /// - content: A ``ViewBuilder`` that you use to declare the views to - /// draw in front of this view, stacked in the order that you list them. - /// The last view that you list appears at the front of the stack. - /// - /// - Returns: A view that uses the specified content as a foreground. - func overlay(alignment: Alignment = .center, @ViewBuilder _ content: () -> Content) -> some View { - self.content.overlay(content(), alignment: alignment) - } - -} diff --git a/SDWebImageSwiftUI/Classes/Backports/StateObject.swift b/SDWebImageSwiftUI/Classes/Backports/StateObject.swift deleted file mode 100644 index 5d47b2b..0000000 --- a/SDWebImageSwiftUI/Classes/Backports/StateObject.swift +++ /dev/null @@ -1,151 +0,0 @@ -import Combine -import SwiftUI - -@available(iOS, deprecated: 14.0) -@available(macOS, deprecated: 11.0) -@available(tvOS, deprecated: 14.0) -@available(watchOS, deprecated: 7.0) -public extension Backport where Wrapped: ObservableObject { - - /// A property wrapper type that instantiates an observable object. - /// - /// Create a state object in a ``SwiftUI/View``, ``SwiftUI/App``, or - /// ``SwiftUI/Scene`` by applying the `@Backport.StateObject` attribute to a property - /// declaration and providing an initial value that conforms to the - /// - /// protocol: - /// - /// @Backport.StateObject var model = DataModel() - /// - /// SwiftUI creates a new instance of the object only once for each instance of - /// the structure that declares the object. When published properties of the - /// observable object change, SwiftUI updates the parts of any view that depend - /// on those properties: - /// - /// Text(model.title) // Updates the view any time `title` changes. - /// - /// You can pass the state object into a property that has the - /// ``SwiftUI/ObservedObject`` attribute. You can alternatively add the object - /// to the environment of a view hierarchy by applying the - /// ``SwiftUI/View/environmentObject(_:)`` modifier: - /// - /// ContentView() - /// .environmentObject(model) - /// - /// If you create an environment object as shown in the code above, you can - /// read the object inside `ContentView` or any of its descendants - /// using the ``SwiftUI/EnvironmentObject`` attribute: - /// - /// @EnvironmentObject var model: DataModel - /// - /// Get a ``SwiftUI/Binding`` to one of the state object's properties using the - /// `$` operator. Use a binding when you want to create a two-way connection to - /// one of the object's properties. For example, you can let a - /// ``SwiftUI/Toggle`` control a Boolean value called `isEnabled` stored in the - /// model: - /// - /// Toggle("Enabled", isOn: $model.isEnabled) - @propertyWrapper struct StateObject: DynamicProperty { - private final class Wrapper: ObservableObject { - private var subject = PassthroughSubject() - - var value: Wrapped? { - didSet { - cancellable = nil - cancellable = value?.objectWillChange - .sink { [subject] _ in subject.send() } - } - } - - private var cancellable: AnyCancellable? - - var objectWillChange: AnyPublisher { - subject.eraseToAnyPublisher() - } - } - - @State private var state = Wrapper() - - @ObservedObject private var observedObject = Wrapper() - - private var thunk: () -> Wrapped - - /// The underlying value referenced by the state object. - /// - /// The wrapped value property provides primary access to the value's data. - /// However, you don't access `wrappedValue` directly. Instead, use the - /// property variable created with the `@Backport.StateObject` attribute: - /// - /// @Backport.StateObject var contact = Contact() - /// - /// var body: some View { - /// Text(contact.name) // Accesses contact's wrapped value. - /// } - /// - /// When you change a property of the wrapped value, you can access the new - /// value immediately. However, SwiftUI updates views displaying the value - /// asynchronously, so the user interface might not update immediately. - public var wrappedValue: Wrapped { - if let object = state.value { - return object - } else { - let object = thunk() - state.value = object - return object - } - } - - /// A projection of the state object that creates bindings to its - /// properties. - /// - /// Use the projected value to pass a binding value down a view hierarchy. - /// To get the projected value, prefix the property variable with `$`. For - /// example, you can get a binding to a model's `isEnabled` Boolean so that - /// a ``SwiftUI/Toggle`` view can control the value: - /// - /// struct MyView: View { - /// @Backport.StateObject var model = DataModel() - /// - /// var body: some View { - /// Toggle("Enabled", isOn: $model.isEnabled) - /// } - /// } - public var projectedValue: ObservedObject.Wrapper { - ObservedObject(wrappedValue: wrappedValue).projectedValue - } - - /// Creates a new state object with an initial wrapped value. - /// - /// You don’t call this initializer directly. Instead, declare a property - /// with the `@Backport.StateObject` attribute in a ``SwiftUI/View``, - /// ``SwiftUI/App``, or ``SwiftUI/Scene``, and provide an initial value: - /// - /// struct MyView: View { - /// @Backport.StateObject var model = DataModel() - /// - /// // ... - /// } - /// - /// SwiftUI creates only one instance of the state object for each - /// container instance that you declare. In the code above, SwiftUI - /// creates `model` only the first time it initializes a particular instance - /// of `MyView`. On the other hand, each different instance of `MyView` - /// receives a distinct copy of the data model. - /// - /// - Parameter thunk: An initial value for the state object. - public init(wrappedValue thunk: @autoclosure @escaping () -> Wrapped) { - self.thunk = thunk - } - - public mutating func update() { - if state.value == nil { - state.value = thunk() - } - if observedObject.value !== state.value { - observedObject.value = state.value - } - } - } - -} - diff --git a/SDWebImageSwiftUI/Classes/Image.swift b/SDWebImageSwiftUI/Classes/Image.swift index 28ba969..4dd60ad 100644 --- a/SDWebImageSwiftUI/Classes/Image.swift +++ b/SDWebImageSwiftUI/Classes/Image.swift @@ -9,7 +9,7 @@ import Foundation import SwiftUI -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension Image { @inlinable init(platformImage: PlatformImage) { #if os(macOS) @@ -20,13 +20,13 @@ extension Image { } } -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension PlatformImage { static var empty = PlatformImage() } #if os(iOS) || os(tvOS) || os(watchOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension PlatformImage.Orientation { @inlinable var toSwiftUI: Image.Orientation { switch self { @@ -52,7 +52,7 @@ extension PlatformImage.Orientation { } } -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension Image.Orientation { @inlinable var toPlatform: PlatformImage.Orientation { switch self { diff --git a/SDWebImageSwiftUI/Classes/ImageManager.swift b/SDWebImageSwiftUI/Classes/ImageManager.swift index d9bce8f..2c134ce 100644 --- a/SDWebImageSwiftUI/Classes/ImageManager.swift +++ b/SDWebImageSwiftUI/Classes/ImageManager.swift @@ -11,7 +11,7 @@ import SDWebImage /// A Image observable object for handle image load process. This drive the Source of Truth for image loading status. /// You can use `@ObservedObject` to associate each instance of manager to your View type, which update your view's body from SwiftUI framework when image was loaded. -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public final class ImageManager : ObservableObject { /// loaded image, note when progressive loading, this will published multiple times with different partial image @Published public var image: PlatformImage? @@ -107,7 +107,7 @@ public final class ImageManager : ObservableObject { } // Completion Handler -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension ImageManager { /// Provide the action when image load fails. /// - Parameters: diff --git a/SDWebImageSwiftUI/Classes/ImagePlayer.swift b/SDWebImageSwiftUI/Classes/ImagePlayer.swift index 4fdc405..4f0f1a8 100644 --- a/SDWebImageSwiftUI/Classes/ImagePlayer.swift +++ b/SDWebImageSwiftUI/Classes/ImagePlayer.swift @@ -10,7 +10,7 @@ import SwiftUI 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. -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public final class ImagePlayer : ObservableObject { var player: SDAnimatedImagePlayer? diff --git a/SDWebImageSwiftUI/Classes/ImageViewWrapper.swift b/SDWebImageSwiftUI/Classes/ImageViewWrapper.swift index 80f936e..e13e92a 100644 --- a/SDWebImageSwiftUI/Classes/ImageViewWrapper.swift +++ b/SDWebImageSwiftUI/Classes/ImageViewWrapper.swift @@ -12,7 +12,7 @@ import SDWebImage #if os(iOS) || os(tvOS) || os(macOS) /// Use wrapper to solve tne `UIImageView`/`NSImageView` frame size become image size issue (SwiftUI's Bug) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public class AnimatedImageViewWrapper : PlatformView { var wrapped = SDAnimatedImageView() var interpolationQuality = CGInterpolationQuality.default @@ -67,7 +67,7 @@ public class AnimatedImageViewWrapper : PlatformView { } /// Use wrapper to solve the `UIProgressView`/`NSProgressIndicator` frame origin NaN crash (SwiftUI's bug) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public class ProgressIndicatorWrapper : PlatformView { #if os(macOS) var wrapped = NSProgressIndicator() @@ -98,7 +98,7 @@ public class ProgressIndicatorWrapper : PlatformView { } } -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension PlatformView { /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview. /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this. diff --git a/SDWebImageSwiftUI/Classes/Indicator/ActivityIndicator.swift b/SDWebImageSwiftUI/Classes/Indicator/ActivityIndicator.swift index 7103c77..2592ebd 100644 --- a/SDWebImageSwiftUI/Classes/Indicator/ActivityIndicator.swift +++ b/SDWebImageSwiftUI/Classes/Indicator/ActivityIndicator.swift @@ -10,7 +10,7 @@ import SwiftUI #if os(macOS) || os(iOS) || os(tvOS) /// An activity indicator (system style) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public struct ActivityIndicator: PlatformViewRepresentable { @Binding var isAnimating: Bool var style: Style @@ -72,7 +72,7 @@ public struct ActivityIndicator: PlatformViewRepresentable { #endif } -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension ActivityIndicator { public enum Style { case medium diff --git a/SDWebImageSwiftUI/Classes/Indicator/Indicator.swift b/SDWebImageSwiftUI/Classes/Indicator/Indicator.swift index 37eb903..69fbb4d 100644 --- a/SDWebImageSwiftUI/Classes/Indicator/Indicator.swift +++ b/SDWebImageSwiftUI/Classes/Indicator/Indicator.swift @@ -10,7 +10,7 @@ import Foundation import SwiftUI /// A type to build the indicator -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public struct Indicator where T : View { var content: (Binding, Binding) -> T @@ -25,7 +25,7 @@ public struct Indicator where T : View { } /// A observable model to report indicator loading status -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public class IndicatorStatus : ObservableObject { /// whether indicator is loading or not @Published var isLoading: Bool = false @@ -36,7 +36,7 @@ public class IndicatorStatus : ObservableObject { /// A implementation detail View Modifier with indicator /// SwiftUI View Modifier construced by using a internal View type which modify the `body` /// It use type system to represent the view hierarchy, and Swift `some View` syntax to hide the type detail for users -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public struct IndicatorViewModifier : ViewModifier where T : View { /// The loading status @@ -45,21 +45,22 @@ public struct IndicatorViewModifier : ViewModifier where T : View { /// The indicator public var indicator: Indicator + @ViewBuilder + private var overlay: some View { + if status.isLoading { + indicator.content($status.isLoading, $status.progress) + } + } + public func body(content: Content) -> some View { ZStack { - content - .backport - .overlay { - if status.isLoading { - indicator.content($status.isLoading, $status.progress) - } - } + content.overlay(overlay, alignment: .center) } } } #if os(macOS) || os(iOS) || os(tvOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension Indicator where T == ActivityIndicator { /// Activity Indicator public static var activity: Indicator { @@ -77,7 +78,7 @@ extension Indicator where T == ActivityIndicator { } } -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension Indicator where T == ProgressIndicator { /// Progress Indicator public static var progress: Indicator { diff --git a/SDWebImageSwiftUI/Classes/Indicator/ProgressIndicator.swift b/SDWebImageSwiftUI/Classes/Indicator/ProgressIndicator.swift index 1256ee8..a017066 100644 --- a/SDWebImageSwiftUI/Classes/Indicator/ProgressIndicator.swift +++ b/SDWebImageSwiftUI/Classes/Indicator/ProgressIndicator.swift @@ -10,7 +10,7 @@ import SwiftUI #if os(macOS) || os(iOS) || os(tvOS) /// A progress bar indicator (system style) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public struct ProgressIndicator: PlatformViewRepresentable { @Binding var isAnimating: Bool @Binding var progress: Double @@ -102,7 +102,7 @@ public struct ProgressIndicator: PlatformViewRepresentable { #endif } -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension ProgressIndicator { public enum Style { case `default` diff --git a/SDWebImageSwiftUI/Classes/SDWebImageSwiftUI.swift b/SDWebImageSwiftUI/Classes/SDWebImageSwiftUI.swift index 9c0e71a..45ae3c2 100644 --- a/SDWebImageSwiftUI/Classes/SDWebImageSwiftUI.swift +++ b/SDWebImageSwiftUI/Classes/SDWebImageSwiftUI.swift @@ -11,53 +11,53 @@ import SwiftUI @_exported import SDWebImage // Automatically import SDWebImage #if os(macOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public typealias PlatformImage = NSImage #else -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public typealias PlatformImage = UIImage #endif #if os(macOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public typealias PlatformView = NSView #endif #if os(iOS) || os(tvOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public typealias PlatformView = UIView #endif #if os(watchOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public typealias PlatformView = WKInterfaceObject #endif #if os(macOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public typealias PlatformViewRepresentable = NSViewRepresentable #endif #if os(iOS) || os(tvOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public typealias PlatformViewRepresentable = UIViewRepresentable #endif #if os(watchOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public typealias PlatformViewRepresentable = WKInterfaceObjectRepresentable #endif #if os(macOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension NSViewRepresentable { typealias PlatformViewType = NSViewType } #endif #if os(iOS) || os(tvOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension UIViewRepresentable { typealias PlatformViewType = UIViewType } #endif #if os(watchOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension WKInterfaceObjectRepresentable { typealias PlatformViewType = WKInterfaceObjectType } diff --git a/SDWebImageSwiftUI/Classes/SwiftUICompatibility.swift b/SDWebImageSwiftUI/Classes/SwiftUICompatibility.swift index e7a4639..1e9f66c 100644 --- a/SDWebImageSwiftUI/Classes/SwiftUICompatibility.swift +++ b/SDWebImageSwiftUI/Classes/SwiftUICompatibility.swift @@ -11,7 +11,7 @@ import SwiftUI #if os(iOS) || os(tvOS) || os(macOS) -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) struct PlatformAppear: PlatformViewRepresentable { let appearAction: () -> Void let disappearAction: () -> Void @@ -38,7 +38,7 @@ struct PlatformAppear: PlatformViewRepresentable { #endif } -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) class PlatformAppearView: PlatformView { var appearAction: () -> Void = {} var disappearAction: () -> Void = {} @@ -74,7 +74,7 @@ class PlatformAppearView: PlatformView { #endif -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension View { /// Used UIKit/AppKit behavior to detect the SwiftUI view's visibility. /// This hack is because of SwiftUI 1.0/2.0 buggy behavior. The built-in `onAppear` and `onDisappear` is so massive on some cases. Where UIKit/AppKit is solid. diff --git a/SDWebImageSwiftUI/Classes/Transition/Transition.swift b/SDWebImageSwiftUI/Classes/Transition/Transition.swift index c4a908f..e42503c 100644 --- a/SDWebImageSwiftUI/Classes/Transition/Transition.swift +++ b/SDWebImageSwiftUI/Classes/Transition/Transition.swift @@ -8,7 +8,7 @@ import SwiftUI -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension AnyTransition { /// Fade-in transition diff --git a/SDWebImageSwiftUI/Classes/WebImage.swift b/SDWebImageSwiftUI/Classes/WebImage.swift index 2290182..faaa423 100644 --- a/SDWebImageSwiftUI/Classes/WebImage.swift +++ b/SDWebImageSwiftUI/Classes/WebImage.swift @@ -10,7 +10,7 @@ import SwiftUI import SDWebImage /// Data Binding Object, only properties in this object can support changes from user with @State and refresh -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) final class WebImageModel : ObservableObject { /// URL image @Published var url: URL? @@ -19,7 +19,7 @@ final class WebImageModel : ObservableObject { } /// Completion Handler Binding Object, supports dynamic @State changes -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) final class WebImageHandler: ObservableObject { // Completion Handler @Published var successBlock: ((PlatformImage, Data?, SDImageCacheType) -> Void)? @@ -28,7 +28,7 @@ final class WebImageHandler: ObservableObject { } /// Configuration Binding Object, supports dynamic @State changes -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) final class WebImageConfiguration: ObservableObject { var retryOnAppear: Bool = true var cancelOnDisappear: Bool = true @@ -42,7 +42,7 @@ final class WebImageConfiguration: ObservableObject { } /// A Image View type to load image from url. Supports static/animated image format. -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public struct WebImage : View { var configurations: [(Image) -> Image] = [] @@ -63,11 +63,9 @@ public struct WebImage : View { @ObservedObject var indicatorStatus : IndicatorStatus - // FIXME: Use SwiftUI StateObject and remove onPlatformAppear once drop iOS 13 support - @Backport.StateObject var imagePlayer = ImagePlayer() + @StateObject var imagePlayer = ImagePlayer() - // FIXME: Use SwiftUI StateObject and remove onPlatformAppear once drop iOS 13 support - @Backport.StateObject var imageManager : ImageManager + @StateObject var imageManager : ImageManager /// Create a web image with url, placeholder, custom options and context. Optional can support animated image using Binding. /// - Parameter url: The image url @@ -89,7 +87,7 @@ public struct WebImage : View { imageModel.context = context _imageModel = ObservedObject(wrappedValue: imageModel) let imageManager = ImageManager() - _imageManager = Backport.StateObject(wrappedValue: imageManager) + _imageManager = StateObject(wrappedValue: imageManager) _indicatorStatus = ObservedObject(wrappedValue: imageManager.indicatorStatus) } @@ -292,7 +290,7 @@ public struct WebImage : View { } // Layout -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension WebImage { func configure(_ block: @escaping (Image) -> Image) -> WebImage { var result = self @@ -330,7 +328,7 @@ extension WebImage { } // Completion Handler -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension WebImage { /// Provide the action when image load fails. @@ -362,7 +360,7 @@ extension WebImage { } // WebImage Modifier -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension WebImage { /// Associate a placeholder when loading image with url @@ -401,7 +399,7 @@ extension WebImage { } // Indicator -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension WebImage { /// Associate a indicator when loading image with url @@ -418,7 +416,7 @@ extension WebImage { } // Animated Image -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) extension WebImage { /// Total loop count for animated image rendering. Defaults to nil. @@ -486,7 +484,7 @@ extension WebImage { } #if DEBUG -@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) +@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) struct WebImage_Previews : PreviewProvider { static var previews: some View { Group {