Yang Chao 2 лет назад
Родитель
Сommit
7508384994

+ 25 - 0
Demo/Demo/Kingfisher-macOS-Demo/Base.lproj/Main.storyboard

@@ -737,6 +737,16 @@
                                     <action selector="reloadPressedWithSender:" target="XfG-lQ-9wD" id="k24-Wi-NRd"/>
                                 </connections>
                             </button>
+                            <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0Du-le-fYN">
+                                <rect key="frame" x="417" y="448" width="78" height="32"/>
+                                <buttonCell key="cell" type="push" title="SwiftUI" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="wIi-ia-bgi">
+                                    <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                    <font key="font" metaFont="system"/>
+                                </buttonCell>
+                                <connections>
+                                    <segue destination="ei1-kq-tvV" kind="show" id="Ub0-4z-BqC"/>
+                                </connections>
+                            </button>
                         </subviews>
                         <constraints>
                             <constraint firstAttribute="trailing" secondItem="MlO-xV-qug" secondAttribute="trailing" id="18w-Qc-Jr6"/>
@@ -745,11 +755,13 @@
                             <constraint firstItem="yIr-uo-Quc" firstAttribute="leading" secondItem="m2S-Jp-Qdl" secondAttribute="leading" constant="20" id="AhA-g2-Cms"/>
                             <constraint firstItem="eLA-Ce-crP" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="yIr-uo-Quc" secondAttribute="trailing" constant="12" symbolic="YES" id="BRb-HY-Dny"/>
                             <constraint firstItem="MlO-xV-qug" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" constant="30" id="Bzu-9v-r7G"/>
+                            <constraint firstItem="0Du-le-fYN" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" constant="5" id="DMs-p7-JWV"/>
                             <constraint firstAttribute="bottom" secondItem="MlO-xV-qug" secondAttribute="bottom" id="HY0-vM-k0l"/>
                             <constraint firstItem="MlO-xV-qug" firstAttribute="leading" secondItem="m2S-Jp-Qdl" secondAttribute="leading" id="Pp3-O7-2Bs"/>
                             <constraint firstItem="eLA-Ce-crP" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" constant="5" id="cJE-Zj-BEy"/>
                             <constraint firstAttribute="trailing" secondItem="Ejh-qu-qmy" secondAttribute="trailing" constant="20" id="eoW-Xb-6wq"/>
                             <constraint firstItem="eLA-Ce-crP" firstAttribute="centerX" secondItem="m2S-Jp-Qdl" secondAttribute="centerX" id="xRm-9b-mgK"/>
+                            <constraint firstItem="Ejh-qu-qmy" firstAttribute="leading" secondItem="0Du-le-fYN" secondAttribute="trailing" constant="50" id="xc2-W0-bu0"/>
                             <constraint firstItem="Ejh-qu-qmy" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" constant="5" id="xnX-II-7iN"/>
                         </constraints>
                     </view>
@@ -761,6 +773,19 @@
             </objects>
             <point key="canvasLocation" x="75" y="831"/>
         </scene>
+        <!--SwiftUI View Controller-->
+        <scene sceneID="Z7V-ea-dRX">
+            <objects>
+                <viewController id="ei1-kq-tvV" customClass="SwiftUIViewController" customModule="Kingfisher_macOS_Demo" customModuleProvider="target" sceneMemberID="viewController">
+                    <view key="view" id="JMh-S8-QlI">
+                        <rect key="frame" x="0.0" y="0.0" width="620" height="474"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                    </view>
+                </viewController>
+                <customObject id="BB8-QC-got" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="75" y="1406"/>
+        </scene>
         <!--Heavy View Controller-->
         <scene sceneID="kQM-gs-M6P">
             <objects>

+ 79 - 0
Demo/Demo/Kingfisher-macOS-Demo/SwiftUIViewController.swift

@@ -0,0 +1,79 @@
+//
+//  SwiftUIViewController.swift
+//  Kingfisher
+//
+//  Created by yeatse on 2024/1/8.
+//
+//  Copyright (c) 2024 Wei Wang <onevcat@gmail.com>
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import SwiftUI
+import Kingfisher
+
+@available(macOS 11, *)
+class SwiftUIViewController: NSHostingController<MainView> {
+    required init?(coder: NSCoder) {
+        super.init(coder: coder, rootView: MainView())
+    }
+}
+
+@available(macOS 11, *)
+struct MainView: View {
+    @State private var index = 1
+    
+    static let gifImageURLs: [URL] = {
+        let prefix = "https://raw.githubusercontent.com/onevcat/Kingfisher-TestImages/master/DemoAppImage/GIF"
+        return (1...3).map { URL(string: "\(prefix)/\($0).gif")! }
+    }()
+        
+    var url: URL {
+        MainView.gifImageURLs[index - 1]
+    }
+    
+    var body: some View {
+        VStack {
+            KFAnimatedImage(url)
+                .configure { view in
+                    view.framePreloadCount = 3
+                }
+                .cacheOriginalImage()
+                .onSuccess { r in
+                    print("suc: \(r)")
+                }
+                .onFailure { e in
+                    print("err: \(e)")
+                }
+                .placeholder { p in
+                    ProgressView(p)
+                }
+                .fade(duration: 1)
+                .forceTransition()
+                .aspectRatio(contentMode: .fill)
+                .frame(width: 300, height: 300)
+                .cornerRadius(20)
+                .shadow(radius: 5)
+                .frame(width: 320, height: 320)
+
+            Button(action: {
+                self.index = (self.index % 3) + 1
+            }) { Text("Next Image") }
+        }
+    }
+}

+ 1 - 1
Sources/SwiftUI/ImageContext.swift

@@ -91,7 +91,7 @@ extension KFImage.Context: Hashable {
     }
 }
 
-#if canImport(UIKit) && !os(watchOS)
+#if !os(watchOS)
 @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
 extension KFAnimatedImage {
     public typealias Context = KFImage.Context

+ 32 - 2
Sources/SwiftUI/KFAnimatedImage.swift

@@ -24,7 +24,7 @@
 //  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 //  THE SOFTWARE.
 
-#if canImport(SwiftUI) && canImport(Combine) && canImport(UIKit) && !os(watchOS)
+#if canImport(SwiftUI) && canImport(Combine) && !os(watchOS)
 import SwiftUI
 import Combine
 
@@ -47,8 +47,9 @@ public struct KFAnimatedImage: KFImageProtocol {
     }
 }
 
+#if !os(macOS)
 /// A wrapped `UIViewRepresentable` of `AnimatedImageView`
-@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
+@available(iOS 14.0, tvOS 14.0, watchOS 7.0, *)
 public struct KFAnimatedImageViewRepresenter: UIViewRepresentable, KFImageHoldingView {
     public typealias RenderingView = AnimatedImageView
     public static func created(from image: KFCrossPlatformImage?, context: KFImage.Context<Self>) -> KFAnimatedImageViewRepresenter {
@@ -75,6 +76,35 @@ public struct KFAnimatedImageViewRepresenter: UIViewRepresentable, KFImageHoldin
         uiView.image = image
     }
 }
+#else
+@available(macOS 11.0, *)
+public struct KFAnimatedImageViewRepresenter: NSViewRepresentable, KFImageHoldingView {
+    public typealias RenderingView = AnimatedImageView
+    public static func created(from image: KFCrossPlatformImage?, context: KFImage.Context<Self>) -> KFAnimatedImageViewRepresenter {
+        KFAnimatedImageViewRepresenter(image: image, context: context)
+    }
+    
+    var image: KFCrossPlatformImage?
+    let context: KFImage.Context<KFAnimatedImageViewRepresenter>
+    
+    public func makeNSView(context: Context) -> AnimatedImageView {
+        let view = AnimatedImageView()
+        
+        self.context.renderConfigurations.forEach { $0(view) }
+        
+        view.image = image
+        
+        // Allow SwiftUI scale (fit/fill) working fine.
+        view.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
+        view.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
+        return view
+    }
+    
+    public func updateNSView(_ nsView: AnimatedImageView, context: Context) {
+        nsView.image = image
+    }
+}
+#endif
 
 #if DEBUG
 @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)