Browse Source

Use optional source for SwiftUI

onevcat 6 years ago
parent
commit
cb85286e8a
2 changed files with 30 additions and 12 deletions
  1. 14 4
      Sources/SwiftUI/ImageBinder.swift
  2. 16 8
      Sources/SwiftUI/KFImage.swift

+ 14 - 4
Sources/SwiftUI/ImageBinder.swift

@@ -35,7 +35,7 @@ extension KFImage {
     /// image downloading and progress reporting based on `KingfisherManager`.
     public class ImageBinder: ObservableObject {
 
-        let source: Source
+        let source: Source?
         let options: KingfisherOptionsInfo?
 
         var downloadTask: DownloadTask?
@@ -65,7 +65,7 @@ extension KFImage {
             #endif
         }
 
-        init(source: Source, options: KingfisherOptionsInfo?) {
+        init(source: Source?, options: KingfisherOptionsInfo?) {
             self.source = source
             self.options = options
             self.image = nil
@@ -76,6 +76,14 @@ extension KFImage {
             guard !loadingOrSuccessed else { return }
 
             loadingOrSuccessed = true
+
+            guard let source = source else {
+                DispatchQueue.main.async {
+                    self.onFailureDelegate.call(KingfisherError.imageSettingError(reason: .emptySource))
+                }
+                return
+            }
+
             downloadTask = KingfisherManager.shared
                 .retrieveImage(
                     with: source,
@@ -91,12 +99,14 @@ extension KFImage {
                         switch result {
                         case .success(let value):
                             self.image = value.image
-                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
+                            DispatchQueue.main.async {
                                 self.onSuccessDelegate.call(value)
                             }
                         case .failure(let error):
                             self.loadingOrSuccessed = false
-                            self.onFailureDelegate.call(error)
+                            DispatchQueue.main.async {
+                                self.onFailureDelegate.call(error)
+                            }
                         }
                 })
         }

+ 16 - 8
Sources/SwiftUI/KFImage.swift

@@ -61,7 +61,7 @@ public struct KFImage: 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) {
+    public init(source: Source?, options: KingfisherOptionsInfo? = nil) {
         binder = ImageBinder(source: source, options: options)
         configurations = []
         binder.start()
@@ -71,13 +71,14 @@ public struct KFImage: 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(.network(url), options: options)
+    public init(_ url: URL?, options: KingfisherOptionsInfo? = nil) {
+        let source = url.map { Source.network($0) }
+        self.init(source: source, options: options)
     }
 
     /// Declares the content and behavior of this view.
     public var body: some View {
-        ZStack {
+        Group {
             if binder.image != nil {
                 configurations
                     .reduce(Image(crossPlatformImage: binder.image!)) {
@@ -85,11 +86,18 @@ public struct KFImage: View {
                     }
                     .animation(binder.fadeTransitionAnimation)
             } else {
-                (placeholder ?? AnyView(Image(crossPlatformImage: .init())))
-                    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
-                    .onDisappear { [unowned binder = self.binder] in
-                        if self.cancelOnDisappear { binder.cancel() }
+                Group {
+                    if placeholder != nil {
+                        placeholder
+                    } else {
+                        Image(crossPlatformImage: .init())
                     }
+                }
+                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
+                .border(Color.black)
+                .onDisappear { [unowned binder = self.binder] in
+                    if self.cancelOnDisappear { binder.cancel() }
+                }
             }
         }.onAppear { [unowned binder] in
             if !binder.loadingOrSuccessed {