Prechádzať zdrojové kódy

Add a progress based placeholder modifier

onevcat 4 rokov pred
rodič
commit
fa0da00a58

+ 2 - 3
Demo/Demo/Kingfisher-Demo/SwiftUIViews/AnimatedImageDemo.swift

@@ -46,9 +46,8 @@ struct AnimatedImageDemo: View {
                 .onFailure { e in
                     print("err: \(e)")
                 }
-                .placeholder {
-                    Image(systemName: "arrow.2.circlepath.circle")
-                        .font(.largeTitle)
+                .placeholder { p in
+                    ProgressView(p)
                 }
                 .fade(duration: 1)
                 .forceTransition()

+ 1 - 2
Demo/Demo/Kingfisher-Demo/SwiftUIViews/SingleViewDemo.swift

@@ -31,7 +31,6 @@ import SwiftUI
 struct SingleViewDemo : View {
 
     @State private var index = 1
-
     @State private var blackWhite = false
 
     var url: URL {
@@ -49,7 +48,7 @@ struct SingleViewDemo : View {
                 .onFailure { e in
                     print("err: \(e)")
                 }
-                .placeholder {
+                .placeholder { progress in
                     Image(systemName: "arrow.2.circlepath.circle")
                         .font(.largeTitle)
                 }

+ 0 - 1
Demo/Demo/Kingfisher-Demo/SwiftUIViews/SizingAnimationDemo.swift

@@ -35,7 +35,6 @@ struct SizingAnimationDemo: View {
     var body: some View {
         VStack {
             KFImage(URL(string: "https://raw.githubusercontent.com/onevcat/Kingfisher-TestImages/master/DemoAppImage/Loading/kingfisher-1.jpg")!)
-                .loadImmediately()
                 .resizable()
                 .aspectRatio(contentMode: .fill)
                 .frame(width: imageSize, height: imageSize)

+ 9 - 0
Sources/SwiftUI/ImageBinder.swift

@@ -48,6 +48,7 @@ extension KFImage {
 
         @Published var loaded = false
         @Published var loadedImage: KFCrossPlatformImage? = nil
+        @Published var progress: Progress = .init()
 
         func start<HoldingView: KFImageHoldingView>(context: Context<HoldingView>) {
 
@@ -60,11 +61,13 @@ extension KFImage {
                 return
             }
 
+            progress = .init()
             downloadTask = KingfisherManager.shared
                 .retrieveImage(
                     with: source,
                     options: context.options,
                     progressBlock: { size, total in
+                        self.updateProgress(downloaded: size, total: total)
                         context.onProgressDelegate.call((size, total))
                     },
                     completionHandler: { [weak self] result in
@@ -93,6 +96,12 @@ extension KFImage {
                         }
                 })
         }
+        
+        private func updateProgress(downloaded: Int64, total: Int64) {
+            progress.totalUnitCount = total
+            progress.completedUnitCount = downloaded
+            objectWillChange.send()
+        }
 
         /// Cancels the download task if it is in progress.
         func cancel() {

+ 1 - 1
Sources/SwiftUI/ImageContext.swift

@@ -39,7 +39,7 @@ extension KFImage {
         var configurations: [(HoldingView) -> HoldingView] = []
         
         var cancelOnDisappear: Bool = false
-        var placeholder: AnyView? = nil
+        var placeholder: ((Progress) -> AnyView)? = nil
 
         let onFailureDelegate = Delegate<KingfisherError, Void>()
         let onSuccessDelegate = Delegate<RetrieveImageResult, Void>()

+ 14 - 3
Sources/SwiftUI/KFImageOptions.swift

@@ -112,12 +112,23 @@ extension KFImageProtocol {
 
 @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
 extension KFImageProtocol {
+    /// Sets a placeholder `View` which shows when loading the image, with a progress parameter as input.
+    /// - Parameter content: A view that describes the placeholder.
+    /// - Returns: A `KFImage` view that contains `content` as its placeholder.
+    public func placeholder<Content: View>(@ViewBuilder _ content: @escaping (Progress) -> Content) -> Self {
+        context.placeholder = { progress in
+            AnyView(content(progress))
+        }
+        return self
+    }
+    
     /// Sets a placeholder `View` which shows when loading the image.
     /// - Parameter content: A view that describes the placeholder.
     /// - Returns: A `KFImage` view that contains `content` as its placeholder.
-    public func placeholder<Content: View>(@ViewBuilder _ content: () -> Content) -> Self {
-        let v = content()
-        context.placeholder = AnyView(v)
+    public func placeholder<Content: View>(@ViewBuilder _ content: @escaping () -> Content) -> Self {
+        context.placeholder = { _ in
+            AnyView(content())
+        }
         return self
     }
 

+ 2 - 2
Sources/SwiftUI/KFImageRenderer.swift

@@ -46,8 +46,8 @@ struct KFImageRenderer<HoldingView> : View where HoldingView: KFImageHoldingView
                     .opacity(binder.loaded ? 1.0 : 0.0)
             } else {
                 Group {
-                    if context.placeholder != nil {
-                        context.placeholder
+                    if let placeholder = context.placeholder {
+                        placeholder(binder.progress)
                     } else {
                         Color.clear
                     }