瀏覽代碼

Move image to view context

onevcat 5 年之前
父節點
當前提交
124952a688
共有 2 個文件被更改,包括 38 次插入37 次删除
  1. 10 6
      Sources/SwiftUI/ImageBinder.swift
  2. 28 31
      Sources/SwiftUI/KFImage.swift

+ 10 - 6
Sources/SwiftUI/ImageBinder.swift

@@ -48,8 +48,6 @@ extension KFImage {
 
         var isLoaded: Binding<Bool>
 
-        @Published var image: KFCrossPlatformImage?
-
         @available(*, deprecated, message: "The `options` version is deprecated And will be removed soon.")
         init(source: Source?, options: KingfisherOptionsInfo? = nil, isLoaded: Binding<Bool>) {
             self.source = source
@@ -61,7 +59,6 @@ extension KFImage {
                 [.loadDiskFileSynchronously]
             )
             self.isLoaded = isLoaded
-            self.image = nil
         }
 
         init(source: Source?, isLoaded: Binding<Bool>) {
@@ -73,10 +70,9 @@ extension KFImage {
                 [.loadDiskFileSynchronously]
             )
             self.isLoaded = isLoaded
-            self.image = nil
         }
 
-        func start() {
+        func start(_ done: @escaping (Result<RetrieveImageResult, KingfisherError>) -> Void) {
 
             guard !loadingOrSucceeded else { return }
 
@@ -103,21 +99,29 @@ extension KFImage {
                         self.downloadTask = nil
                         switch result {
                         case .success(let value):
+
                             // The normalized version of image is used to solve #1395
                             // It should be not necessary if SwiftUI.Image can handle resizing correctly when created
                             // by `Image.init(uiImage:)`. (The orientation information should be already contained in
                             // a `UIImage`)
                             // https://github.com/onevcat/Kingfisher/issues/1395
                             let image = value.image.kf.normalized
+                            let r = RetrieveImageResult(
+                                image: image, cacheType: value.cacheType, source: value.source, originalSource: value.originalSource
+                            )
                             CallbackQueue.mainCurrentOrAsync.execute {
-                                self.image = image
+                                done(.success(r))
                             }
+
                             CallbackQueue.mainAsync.execute {
                                 self.isLoaded.wrappedValue = true
                                 self.onSuccessDelegate.call(value)
                             }
                         case .failure(let error):
                             self.loadingOrSucceeded = false
+                            CallbackQueue.mainCurrentOrAsync.execute {
+                                done(.failure(error))
+                            }
                             CallbackQueue.mainAsync.execute {
                                 self.onFailureDelegate.call(error)
                             }

+ 28 - 31
Sources/SwiftUI/KFImage.swift

@@ -49,6 +49,8 @@ public struct KFImage: View {
     /// An image binder that manages loading and cancelling image related task.
     @ObservedObject private(set) var binder: ImageBinder
 
+    @State private var loadingResult: Result<RetrieveImageResult, KingfisherError>?
+
     // Acts as a placeholder when loading an image.
     var placeholder: AnyView?
 
@@ -73,7 +75,6 @@ public struct KFImage: View {
         let binder = ImageBinder(source: source, options: options, isLoaded: isLoaded)
         self.binder = binder
         configurations = []
-        binder.start()
     }
 
     /// Creates a Kingfisher compatible image view to load image from the given `URL`.
@@ -101,8 +102,6 @@ public struct KFImage: View {
         let binder = ImageBinder(source: source, isLoaded: isLoaded)
         self.binder = binder
         configurations = []
-        // Give the `binder` a chance to accept other options.
-        DispatchQueue.main.async { binder.start() }
     }
 
     /// Creates a Kingfisher compatible image view to load image from the given `URL`.
@@ -117,36 +116,34 @@ public struct KFImage: View {
 
     /// Declares the content and behavior of this view.
     public var body: some View {
-        Group {
-            if binder.image != nil {
-                configurations
-                    .reduce(Image(crossPlatformImage: binder.image!)) {
-                        current, config in config(current)
-                    }
-            } else {
-                Group {
-                    if placeholder != nil {
-                        placeholder
-                    } else {
-                        Image(crossPlatformImage: .init())
-                    }
+
+        if case .success(let r) = loadingResult {
+            configurations
+                .reduce(Image(crossPlatformImage: r.image)) {
+                    current, config in config(current)
+                }
+        } else {
+            Group {
+                if placeholder != nil {
+                    placeholder
+                } else {
+                    Image(crossPlatformImage: .init())
                 }
-                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
-                .onAppear { [weak binder = self.binder] in
-                    guard let binder = binder else {
-                        return
-                    }
-                    if !binder.loadingOrSucceeded {
-                        binder.start()
-                    }
+            }
+            .onAppear { [weak binder = self.binder] in
+                guard let binder = binder else {
+                    return
+                }
+                if !binder.loadingOrSucceeded {
+                    binder.start { self.loadingResult = $0 }
+                }
+            }
+            .onDisappear { [weak binder = self.binder] in
+                guard let binder = binder else {
+                    return
                 }
-                .onDisappear { [weak binder = self.binder] in
-                    guard let binder = binder else {
-                        return
-                    }
-                    if self.cancelOnDisappear {
-                        binder.cancel()
-                    }
+                if self.cancelOnDisappear {
+                    binder.cancel()
                 }
             }
         }