Added visionOS support

Add visionOS Demo

The scale using traitCollection.displayScale
This commit is contained in:
DreamPiggy 2023-06-22 19:20:01 +08:00
parent e837c37d45
commit 2d4839a195
28 changed files with 537 additions and 506 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,6 @@
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "self:SDWebImageSwiftUI.xcodeproj"> location = "self:">
</FileRef> </FileRef>
</Workspace> </Workspace>

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1500"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "32D5D15F2A445B250098BDFC"
BuildableName = "SDWebImageSwiftUIDemo-visionOS.app"
BlueprintName = "SDWebImageSwiftUIDemo-visionOS"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "32D5D15F2A445B250098BDFC"
BuildableName = "SDWebImageSwiftUIDemo-visionOS.app"
BlueprintName = "SDWebImageSwiftUIDemo-visionOS"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "32D5D15F2A445B250098BDFC"
BuildableName = "SDWebImageSwiftUIDemo-visionOS.app"
BlueprintName = "SDWebImageSwiftUIDemo-visionOS"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -54,10 +54,8 @@
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal" debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<RemoteRunnable <BuildableProductRunnable
runnableDebuggingMode = "2" runnableDebuggingMode = "0">
BundleIdentifier = "com.apple.Carousel"
RemotePath = "/SDWebImageSwiftUIDemo-watchOS WatchKit App">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "32E529362348A0DD00EA46FF" BlueprintIdentifier = "32E529362348A0DD00EA46FF"
@ -65,7 +63,7 @@
BlueprintName = "SDWebImageSwiftUIDemo-watchOS WatchKit App" BlueprintName = "SDWebImageSwiftUIDemo-watchOS WatchKit App"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj"> ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference> </BuildableReference>
</RemoteRunnable> </BuildableProductRunnable>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release" buildConfiguration = "Release"
@ -73,10 +71,8 @@
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<RemoteRunnable <BuildableProductRunnable
runnableDebuggingMode = "2" runnableDebuggingMode = "0">
BundleIdentifier = "com.apple.Carousel"
RemotePath = "/SDWebImageSwiftUIDemo-watchOS WatchKit App">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "32E529362348A0DD00EA46FF" BlueprintIdentifier = "32E529362348A0DD00EA46FF"
@ -84,16 +80,7 @@
BlueprintName = "SDWebImageSwiftUIDemo-watchOS WatchKit App" BlueprintName = "SDWebImageSwiftUIDemo-watchOS WatchKit App"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj"> ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference> </BuildableReference>
</RemoteRunnable> </BuildableProductRunnable>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "32E529362348A0DD00EA46FF"
BuildableName = "SDWebImageSwiftUIDemo-watchOS WatchKit App.app"
BlueprintName = "SDWebImageSwiftUIDemo-watchOS WatchKit App"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction> </ProfileAction>
<AnalyzeAction <AnalyzeAction
buildConfiguration = "Debug"> buildConfiguration = "Debug">

View File

@ -0,0 +1,41 @@
/*
* This file is part of the SDWebImage package.
* (c) DreamPiggy <lizhuoli1126@126.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import SwiftUI
import UIKit
import SDWebImage
// no changes in your AppDelegate class
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
// Add WebP/SVG/PDF support
SDImageCodersManager.shared.addCoder(SDImageAWebPCoder.shared)
// Dynamic check to support vector format for both WebImage/AnimatedImage
SDWebImageManager.shared.optionsProcessor = SDWebImageOptionsProcessor { url, options, context in
var options = options
if let _ = context?[.animatedImageClass] as? SDAnimatedImage.Type {
// AnimatedImage supports vector rendering, should not force decode
options.insert(.avoidDecodeImage)
}
return SDWebImageOptionsResult(options: options, context: context)
}
return true
}
}
@main
struct SDWebImageSwiftUIDemo: App {
// inject into SwiftUI life-cycle via adaptor
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "reality",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,17 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"layers" : [
{
"filename" : "Front.solidimagestacklayer"
},
{
"filename" : "Middle.solidimagestacklayer"
},
{
"filename" : "Back.solidimagestacklayer"
}
]
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "reality",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "reality",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -112,7 +112,7 @@ struct ContentView: View {
NavigationLink(destination: DetailView(url: url, animated: self.animated)) { NavigationLink(destination: DetailView(url: url, animated: self.animated)) {
HStack { HStack {
if self.animated { if self.animated {
#if os(macOS) || os(iOS) || os(tvOS) #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS)
AnimatedImage(url: URL(string:url), isAnimating: .constant(true)) AnimatedImage(url: URL(string:url), isAnimating: .constant(true))
.onViewUpdate { view, context in .onViewUpdate { view, context in
#if os(macOS) #if os(macOS)
@ -157,6 +157,20 @@ struct ContentView: View {
var body: some View { var body: some View {
#if os(visionOS)
return NavigationView {
contentView()
.navigationBarTitle(animated ? "AnimatedImage" : "WebImage")
.navigationBarItems(leading:
Button(action: { self.reloadCache() }) {
Text("Reload")
}, trailing:
Button(action: { self.switchView() }) {
Text("Switch")
}
)
}
#endif
#if os(iOS) #if os(iOS)
return NavigationView { return NavigationView {
contentView() contentView()

View File

@ -44,7 +44,7 @@ struct DetailView: View {
var body: some View { var body: some View {
VStack { VStack {
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS) || os(visionOS)
zoomView() zoomView()
.navigationBarItems(trailing: Button(isAnimating ? "Stop" : "Start") { .navigationBarItems(trailing: Button(isAnimating ? "Stop" : "Start") {
self.isAnimating.toggle() self.isAnimating.toggle()
@ -62,7 +62,7 @@ struct DetailView: View {
} }
func zoomView() -> some View { func zoomView() -> some View {
#if os(macOS) || os(iOS) #if os(macOS) || os(iOS) || os(visionOS)
return contentView() return contentView()
.scaleEffect(self.scale) .scaleEffect(self.scale)
.gesture(MagnificationGesture(minimumScaleDelta: 0.1).onChanged { value in .gesture(MagnificationGesture(minimumScaleDelta: 0.1).onChanged { value in
@ -94,7 +94,7 @@ struct DetailView: View {
func contentView() -> some View { func contentView() -> some View {
HStack { HStack {
if animated { if animated {
#if os(macOS) || os(iOS) || os(tvOS) #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS)
AnimatedImage(url: URL(string:url), options: [.progressiveLoad, .delayPlaceholder], isAnimating: $isAnimating) AnimatedImage(url: URL(string:url), options: [.progressiveLoad, .delayPlaceholder], isAnimating: $isAnimating)
.resizable() .resizable()
.placeholder(.wifiExclamationmark) .placeholder(.wifiExclamationmark)

View File

@ -403,8 +403,6 @@
Base, Base,
); );
mainGroup = 32C43DC222FD540D00BE87F5; mainGroup = 32C43DC222FD540D00BE87F5;
packageReferences = (
);
productRefGroup = 32C43DCD22FD540D00BE87F5 /* Products */; productRefGroup = 32C43DCD22FD540D00BE87F5 /* Products */;
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";

View File

@ -4,7 +4,4 @@
<FileRef <FileRef
location = "group:Example/SDWebImageSwiftUI.xcodeproj"> location = "group:Example/SDWebImageSwiftUI.xcodeproj">
</FileRef> </FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace> </Workspace>

View File

@ -9,7 +9,7 @@
import SwiftUI import SwiftUI
import SDWebImage import SDWebImage
#if os(iOS) || os(tvOS) || os(macOS) #if !os(watchOS)
/// A coordinator object used for `AnimatedImage`native view bridge for UIKit/AppKit. /// 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 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
@ -183,7 +183,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
#if os(macOS) #if os(macOS)
public typealias NSViewType = AnimatedImageViewWrapper public typealias NSViewType = AnimatedImageViewWrapper
#elseif os(iOS) || os(tvOS) #else
public typealias UIViewType = AnimatedImageViewWrapper public typealias UIViewType = AnimatedImageViewWrapper
#endif #endif
@ -205,7 +205,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
public static func dismantleNSView(_ nsView: AnimatedImageViewWrapper, coordinator: Coordinator) { public static func dismantleNSView(_ nsView: AnimatedImageViewWrapper, coordinator: Coordinator) {
dismantleView(nsView, coordinator: coordinator) dismantleView(nsView, coordinator: coordinator)
} }
#elseif os(iOS) || os(tvOS) #else
public func makeUIView(context: Context) -> AnimatedImageViewWrapper { public func makeUIView(context: Context) -> AnimatedImageViewWrapper {
makeView(context: context) makeView(context: context)
} }
@ -373,14 +373,14 @@ public struct AnimatedImage : PlatformViewRepresentable {
// AspectRatio && ContentMode // AspectRatio && ContentMode
#if os(macOS) #if os(macOS)
let contentMode: NSImageScaling let contentMode: NSImageScaling
#elseif os(iOS) || os(tvOS) #else
let contentMode: UIView.ContentMode let contentMode: UIView.ContentMode
#endif #endif
if let _ = imageLayout.aspectRatio { if let _ = imageLayout.aspectRatio {
// If `aspectRatio` is not `nil`, always scale to fill and SwiftUI will layout the container with custom aspect ratio. // If `aspectRatio` is not `nil`, always scale to fill and SwiftUI will layout the container with custom aspect ratio.
#if os(macOS) #if os(macOS)
contentMode = .scaleAxesIndependently contentMode = .scaleAxesIndependently
#elseif os(iOS) || os(tvOS) #else
contentMode = .scaleToFill contentMode = .scaleToFill
#endif #endif
} else { } else {
@ -391,20 +391,20 @@ public struct AnimatedImage : PlatformViewRepresentable {
// Actually, NSImageView have no `.aspectFill` unlike UIImageView, only `CALayerContentsGravity.resizeAspectFill` have the same concept // Actually, NSImageView have no `.aspectFill` unlike UIImageView, only `CALayerContentsGravity.resizeAspectFill` have the same concept
// However, using `.scaleProportionallyUpOrDown`, SwiftUI still layout the HostingView correctly, so this is OK // However, using `.scaleProportionallyUpOrDown`, SwiftUI still layout the HostingView correctly, so this is OK
contentMode = .scaleProportionallyUpOrDown contentMode = .scaleProportionallyUpOrDown
#elseif os(iOS) || os(tvOS) #else
contentMode = .scaleAspectFill contentMode = .scaleAspectFill
#endif #endif
case .fit: case .fit:
#if os(macOS) #if os(macOS)
contentMode = .scaleProportionallyUpOrDown contentMode = .scaleProportionallyUpOrDown
#elseif os(iOS) || os(tvOS) #else
contentMode = .scaleAspectFit contentMode = .scaleAspectFit
#endif #endif
case .none: case .none:
// If `contentMode` is not set at all, using scale to fill as SwiftUI default value // If `contentMode` is not set at all, using scale to fill as SwiftUI default value
#if os(macOS) #if os(macOS)
contentMode = .scaleAxesIndependently contentMode = .scaleAxesIndependently
#elseif os(iOS) || os(tvOS) #else
contentMode = .scaleToFill contentMode = .scaleToFill
#endif #endif
} }

View File

@ -25,7 +25,7 @@ extension PlatformImage {
static var empty = PlatformImage() static var empty = PlatformImage()
} }
#if os(iOS) || os(tvOS) || os(watchOS) #if !os(macOS)
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension PlatformImage.Orientation { extension PlatformImage.Orientation {
@inlinable var toSwiftUI: Image.Orientation { @inlinable var toSwiftUI: Image.Orientation {

View File

@ -9,7 +9,7 @@
import Foundation import Foundation
import SDWebImage import SDWebImage
#if os(iOS) || os(tvOS) || os(macOS) #if !os(watchOS)
/// Use wrapper to solve tne `UIImageView`/`NSImageView` frame size become image size issue (SwiftUI's Bug) /// 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 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)

View File

@ -8,7 +8,7 @@
import SwiftUI import SwiftUI
#if os(macOS) || os(iOS) || os(tvOS) #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS)
/// An activity indicator (system style) /// An activity indicator (system style)
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct ActivityIndicator: PlatformViewRepresentable { public struct ActivityIndicator: PlatformViewRepresentable {
@ -26,11 +26,11 @@ public struct ActivityIndicator: PlatformViewRepresentable {
#if os(macOS) #if os(macOS)
public typealias NSViewType = NSProgressIndicator public typealias NSViewType = NSProgressIndicator
#elseif os(iOS) || os(tvOS) #else
public typealias UIViewType = UIActivityIndicatorView public typealias UIViewType = UIActivityIndicatorView
#endif #endif
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS) || os(visionOS)
public func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView { public func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView {
let activityStyle: UIActivityIndicatorView.Style let activityStyle: UIActivityIndicatorView.Style
switch style { switch style {

View File

@ -58,7 +58,7 @@ public struct IndicatorViewModifier<T> : ViewModifier where T : View {
} }
} }
#if os(macOS) || os(iOS) || os(tvOS) #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS)
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Indicator where T == ActivityIndicator { extension Indicator where T == ActivityIndicator {
/// Activity Indicator /// Activity Indicator

View File

@ -8,7 +8,7 @@
import SwiftUI import SwiftUI
#if os(macOS) || os(iOS) || os(tvOS) #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS)
/// A progress bar indicator (system style) /// A progress bar indicator (system style)
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct ProgressIndicator: PlatformViewRepresentable { public struct ProgressIndicator: PlatformViewRepresentable {
@ -29,11 +29,11 @@ public struct ProgressIndicator: PlatformViewRepresentable {
#if os(macOS) #if os(macOS)
public typealias NSViewType = ProgressIndicatorWrapper public typealias NSViewType = ProgressIndicatorWrapper
#elseif os(iOS) || os(tvOS) #else
public typealias UIViewType = ProgressIndicatorWrapper public typealias UIViewType = ProgressIndicatorWrapper
#endif #endif
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS) || os(visionOS)
public func makeUIView(context: UIViewRepresentableContext<ProgressIndicator>) -> ProgressIndicatorWrapper { public func makeUIView(context: UIViewRepresentableContext<ProgressIndicator>) -> ProgressIndicatorWrapper {
let progressStyle: UIProgressView.Style let progressStyle: UIProgressView.Style
switch style { switch style {

View File

@ -22,7 +22,7 @@ public typealias PlatformImage = UIImage
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public typealias PlatformView = NSView public typealias PlatformView = NSView
#endif #endif
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS) || os(visionOS)
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public typealias PlatformView = UIView public typealias PlatformView = UIView
#endif #endif
@ -35,7 +35,7 @@ public typealias PlatformView = WKInterfaceObject
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public typealias PlatformViewRepresentable = NSViewRepresentable public typealias PlatformViewRepresentable = NSViewRepresentable
#endif #endif
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS) || os(visionOS)
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public typealias PlatformViewRepresentable = UIViewRepresentable public typealias PlatformViewRepresentable = UIViewRepresentable
#endif #endif
@ -50,7 +50,7 @@ extension NSViewRepresentable {
typealias PlatformViewType = NSViewType typealias PlatformViewType = NSViewType
} }
#endif #endif
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS) || os(visionOS)
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension UIViewRepresentable { extension UIViewRepresentable {
typealias PlatformViewType = UIViewType typealias PlatformViewType = UIViewType

View File

@ -9,14 +9,14 @@
import Foundation import Foundation
import SwiftUI import SwiftUI
#if os(iOS) || os(tvOS) || os(macOS) #if !os(watchOS)
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
struct PlatformAppear: PlatformViewRepresentable { struct PlatformAppear: PlatformViewRepresentable {
let appearAction: () -> Void let appearAction: () -> Void
let disappearAction: () -> Void let disappearAction: () -> Void
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS) || os(visionOS)
func makeUIView(context: Context) -> some UIView { func makeUIView(context: Context) -> some UIView {
let view = PlatformAppearView() let view = PlatformAppearView()
view.appearAction = appearAction view.appearAction = appearAction

View File

@ -64,10 +64,10 @@ public struct WebImage : View {
@ObservedObject var indicatorStatus : IndicatorStatus @ObservedObject var indicatorStatus : IndicatorStatus
// FIXME: Use SwiftUI StateObject and remove onPlatformAppear once drop iOS 13 support // 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 // 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. /// Create a web image with url, placeholder, custom options and context. Optional can support animated image using Binding.
/// - Parameter url: The image url /// - Parameter url: The image url
@ -89,7 +89,7 @@ public struct WebImage : View {
imageModel.context = context imageModel.context = context
_imageModel = ObservedObject(wrappedValue: imageModel) _imageModel = ObservedObject(wrappedValue: imageModel)
let imageManager = ImageManager() let imageManager = ImageManager()
_imageManager = Backport.StateObject(wrappedValue: imageManager) _imageManager = StateObject(wrappedValue: imageManager)
_indicatorStatus = ObservedObject(wrappedValue: imageManager.indicatorStatus) _indicatorStatus = ObservedObject(wrappedValue: imageManager.indicatorStatus)
} }
@ -160,9 +160,11 @@ public struct WebImage : View {
// ensure CGImage is nil // ensure CGImage is nil
if image.cgImage == nil { if image.cgImage == nil {
// draw vector into bitmap with the screen scale (behavior like AppKit) // draw vector into bitmap with the screen scale (behavior like AppKit)
#if os(iOS) || os(tvOS) #if os(visionOS)
let scale = UITraitCollection.current.displayScale
#elseif os(iOS) || os(tvOS) || os(visionOS)
let scale = UIScreen.main.scale let scale = UIScreen.main.scale
#else #elseif os(watchOS)
let scale = WKInterfaceDevice.current().screenScale let scale = WKInterfaceDevice.current().screenScale
#endif #endif
UIGraphicsBeginImageContextWithOptions(image.size, false, scale) UIGraphicsBeginImageContextWithOptions(image.size, false, scale)