Selaa lähdekoodia

Generic placeholder type and cancel on disappear

onevcat 6 vuotta sitten
vanhempi
commit
1d354ed1f3

+ 11 - 3
Demo/Demo/Kingfisher-Demo/ViewControllers/SwiftUIScreens/SwiftUIList.swift

@@ -39,12 +39,20 @@ struct SwiftUIList : View {
                 KFImage(URL(string: "https://github.com/onevcat/Flower-Data-Set/raw/master/rose/rose-\(i).jpg")!)
                     .resizable()
                     .onSuccess { r in
-                        print("suc: \(i) - \(r.cacheType)")
+                        print("Success: \(i) - \(r.cacheType)")
                     }
                     .onFailure { e in
-                        print("err: \(i)")
+                        print("Error: \(e)")
                     }
-                    .placeholder(image: Image(systemName: "arrow.2.circlepath.circle"))
+                    .onProgress { downloaded, total in
+                        print("\(downloaded) / \(total))")
+                    }
+                    .placeholder {
+                        Image(systemName: "arrow.2.circlepath.circle")
+                            .resizable()
+                            .frame(width: 80, height: 80)
+                    }
+                    .cancelOnDisappear(true)
                     .aspectRatio(contentMode: .fit)
                     .cornerRadius(20)
                     .frame(width: 300, height: 300)

+ 3 - 1
Demo/Demo/Kingfisher-Demo/ViewControllers/SwiftUIScreens/SwiftUIView.swift

@@ -45,7 +45,9 @@ struct SwiftUIView : View {
                     print("err: \(e)")
                     self.result = "\(e)"
                 }
-                .placeholder(image: Image(systemName: "star.fill"))
+                .placeholder {
+                    Image(systemName: "star.fill")
+                }
                 .frame(width: 300, height: 300)
                 .cornerRadius(20)
 

+ 35 - 15
Sources/SwiftUI/KFImage.swift

@@ -40,13 +40,20 @@ extension Image {
 }
 
 @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
-public struct KFImage: View {
+extension View {
+    func eraseToAnyView() -> AnyView { .init(self) }
+}
 
-    var placeholder = Image(crossPlatformImage: .init())
-    var configs: [(Image) -> Image]
+@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
+public struct KFImage: View {
 
     @ObjectBinding public private(set) var binder: ImageBinder
 
+    var placeholder: AnyView?
+    var cancelOnDisappear: Bool = false
+    
+    var configs: [(Image) -> Image]
+
     public init(_ source: Source, options: KingfisherOptionsInfo? = nil) {
         binder = ImageBinder(source: source, options: options)
         configs = []
@@ -57,12 +64,26 @@ public struct KFImage: View {
     }
 
     public var body: some View {
-        let image = binder.image.map { Image(crossPlatformImage: $0) } ?? placeholder
-        return configs
-            .reduce(image) { current, config in config(current) }
-            .onAppear { [unowned binder] in
+        if let image = binder.image {
+            let result = configs.reduce(Image(crossPlatformImage: image)) {
+                current, config in
+                config(current)
+            }
+            return AnyView(result)
+        } else {
+            let result = placeholder ?? AnyView(Image(crossPlatformImage: .init()))
+            let onAppear = result.onAppear { [unowned binder] in
                 binder.start()
             }
+
+            if cancelOnDisappear {
+                return onAppear.onDisappear { [unowned binder] in
+                    binder.cancel()
+                }.eraseToAnyView()
+            } else {
+                return onAppear.eraseToAnyView()
+            }
+        }
     }
 }
 
@@ -94,18 +115,17 @@ extension KFImage {
         config { $0.antialiased(isAntialiased) }
     }
 
-    public func placeholder(image: Image?) -> KFImage {
+    public func placeholder<Content: View>(@ViewBuilder _ content: () -> Content) -> KFImage {
+        let v = content()
         var result = self
-        result.placeholder = image ?? Image(crossPlatformImage: .init())
+        result.placeholder = AnyView(v)
         return result
     }
 
-    public func placeholder(name: String, bundle: Bundle? = nil) -> KFImage {
-        return placeholder(image: .init(name, bundle: bundle))
-    }
-
-    public func placeholder(systemName: String) -> KFImage {
-        return placeholder(image: .init(systemName: systemName))
+    public func cancelOnDisappear(_ flag: Bool) -> KFImage {
+        var result = self
+        result.cancelOnDisappear = flag
+        return result
     }
 }