Browse Source

Merge pull request #1429 from onevcat/feature/isLoaded-binding

Add isLoaded binding for better SwiftUI approach
Wei Wang 5 years ago
parent
commit
e2fb22d32d

+ 1 - 2
Demo/Demo/Kingfisher-SwiftUI-Demo/Views/SwiftUIList.swift

@@ -54,10 +54,9 @@ struct SwiftUIList : View {
         var body: some View {
             HStack(alignment: .center) {
                 Spacer()
-                KFImage(url)
+                KFImage(url, isLoaded: $done)
                     .resizable()
                     .onSuccess { r in
-                        self.done = true
                         print("Success: \(self.index) - \(r.cacheType)")
                     }
                     .onFailure { e in

+ 8 - 4
Sources/SwiftUI/ImageBinder.swift

@@ -49,11 +49,14 @@ extension KFImage {
         let onSuccessDelegate = Delegate<RetrieveImageResult, Void>()
         let onProgressDelegate = Delegate<(Int64, Int64), Void>()
 
+        var isLoaded: Binding<Bool>
+
         @Published var image: KFCrossPlatformImage?
 
-        init(source: Source?, options: KingfisherOptionsInfo?) {
+        init(source: Source?, options: KingfisherOptionsInfo?, isLoaded: Binding<Bool>) {
             self.source = source
             self.options = options
+            self.isLoaded = isLoaded
             self.image = nil
         }
 
@@ -91,6 +94,7 @@ extension KFImage {
                             // https://github.com/onevcat/Kingfisher/issues/1395
                             self.image = value.image.kf.normalized
                             DispatchQueue.main.async {
+                                self.isLoaded.wrappedValue = true
                                 self.onSuccessDelegate.call(value)
                             }
                         case .failure(let error):
@@ -108,19 +112,19 @@ extension KFImage {
         }
 
         func setOnFailure(perform action: ((KingfisherError) -> Void)?) {
-            onFailureDelegate.delegate(on: self) { _, error in
+            onFailureDelegate.delegate(on: self) { (self, error) in
                 action?(error)
             }
         }
 
         func setOnSuccess(perform action: ((RetrieveImageResult) -> Void)?) {
-            onSuccessDelegate.delegate(on: self) { _, result in
+            onSuccessDelegate.delegate(on: self) { (self, result) in
                 action?(result)
             }
         }
 
         func setOnProgress(perform action: ((Int64, Int64) -> Void)?) {
-            onProgressDelegate.delegate(on: self) { _, result in
+            onProgressDelegate.delegate(on: self) { (self, result) in
                 action?(result.0, result.1)
             }
         }

+ 10 - 4
Sources/SwiftUI/KFImage.swift

@@ -64,8 +64,11 @@ public struct KFImage: SwiftUI.View {
     /// - Parameter source: The image `Source` defining where to load the target image.
     /// - Parameter options: The options should be applied when loading the image.
     ///                      Some UIKit related options (such as `ImageTransition.flip`) are not supported.
-    public init(source: Source?, options: KingfisherOptionsInfo? = nil) {
-        binder = ImageBinder(source: source, options: options)
+    /// - Parameter isLoaded: Whether the image is loaded or not. This provides a way to inspect the internal loading
+    ///                       state. `true` if the image is loaded successfully. Otherwise, `false`. Do not set the
+    ///                       wrapped value from outside.
+    public init(source: Source?, options: KingfisherOptionsInfo? = nil, isLoaded: Binding<Bool> = .constant(false)) {
+        binder = ImageBinder(source: source, options: options, isLoaded: isLoaded)
         configurations = []
         binder.start()
     }
@@ -74,8 +77,11 @@ public struct KFImage: SwiftUI.View {
     /// - Parameter url: The image URL from where to load the target image.
     /// - Parameter options: The options should be applied when loading the image.
     ///                      Some UIKit related options (such as `ImageTransition.flip`) are not supported.
-    public init(_ url: URL?, options: KingfisherOptionsInfo? = nil) {
-        self.init(source: url?.convertToSource(), options: options)
+    /// - Parameter isLoaded: Whether the image is loaded or not. This provides a way to inspect the internal loading
+    ///                       state. `true` if the image is loaded successfully. Otherwise, `false`. Do not set the
+    ///                       wrapped value from outside.
+    public init(_ url: URL?, options: KingfisherOptionsInfo? = nil, isLoaded: Binding<Bool> = .constant(false)) {
+        self.init(source: url?.convertToSource(), options: options, isLoaded: isLoaded)
     }
 
     /// Declares the content and behavior of this view.