Explorar el Código

feat: add PHPickerResultImageDataProvider

nuomi1 hace 1 año
padre
commit
76d8923138

+ 4 - 0
Kingfisher.xcodeproj/project.pbxproj

@@ -8,6 +8,7 @@
 
 /* Begin PBXBuildFile section */
 		07292245263B02F00089E810 /* KFAnimatedImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07292244263B02F00089E810 /* KFAnimatedImage.swift */; };
+		078DCB4F2BCFEB7D0008114E /* PHPickerResultImageDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 078DCB4E2BCFEB7D0008114E /* PHPickerResultImageDataProvider.swift */; };
 		22FDCE0E2700078B0044D11E /* CPListItem+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22FDCE0D2700078B0044D11E /* CPListItem+Kingfisher.swift */; };
 		388F37382B4D9CDB0089705C /* DisplayLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 388F37372B4D9CDB0089705C /* DisplayLink.swift */; };
 		4B10480D216F157000300C61 /* ImageDataProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B10480C216F157000300C61 /* ImageDataProcessor.swift */; };
@@ -148,6 +149,7 @@
 
 /* Begin PBXFileReference section */
 		07292244263B02F00089E810 /* KFAnimatedImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KFAnimatedImage.swift; sourceTree = "<group>"; };
+		078DCB4E2BCFEB7D0008114E /* PHPickerResultImageDataProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHPickerResultImageDataProvider.swift; sourceTree = "<group>"; };
 		185218B51CC07F8300BD58DE /* NSButtonExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSButtonExtensionTests.swift; sourceTree = "<group>"; };
 		22FDCE0D2700078B0044D11E /* CPListItem+Kingfisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CPListItem+Kingfisher.swift"; sourceTree = "<group>"; };
 		388F37372B4D9CDB0089705C /* DisplayLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayLink.swift; sourceTree = "<group>"; };
@@ -655,6 +657,7 @@
 				D12AB69E215D2BB50013BA68 /* Resource.swift */,
 				D1E56444219B16330057AAE3 /* ImageDataProvider.swift */,
 				D16CC3D524E02E9500F1A515 /* AVAssetImageDataProvider.swift */,
+				078DCB4E2BCFEB7D0008114E /* PHPickerResultImageDataProvider.swift */,
 			);
 			path = ImageSource;
 			sourceTree = "<group>";
@@ -850,6 +853,7 @@
 				D12AB714215D2BB50013BA68 /* ImageCache.swift in Sources */,
 				4B88CEB02646C056009EBB41 /* KFImageProtocol.swift in Sources */,
 				D12AB6D0215D2BB50013BA68 /* ImagePrefetcher.swift in Sources */,
+				078DCB4F2BCFEB7D0008114E /* PHPickerResultImageDataProvider.swift in Sources */,
 				388F37382B4D9CDB0089705C /* DisplayLink.swift in Sources */,
 				D12AB6F4215D2BB50013BA68 /* ImageView+Kingfisher.swift in Sources */,
 				D12AB6FC215D2BB50013BA68 /* UIButton+Kingfisher.swift in Sources */,

+ 81 - 0
Sources/General/ImageSource/PHPickerResultImageDataProvider.swift

@@ -0,0 +1,81 @@
+//
+//  PHPickerResultImageDataProvider.swift
+//  Kingfisher
+//
+//  Created by nuomi1 on 2024-04-17.
+//
+//  Copyright (c) 2024 Wei Wang <onevcat@gmail.com>
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+import Foundation
+import PhotosUI
+
+/// A data provider to provide image data from a given `PHPickerResult`.
+@available(iOS 14.0, macOS 13.0, *)
+@available(watchOS, unavailable)
+@available(tvOS, unavailable)
+public struct PHPickerResultImageDataProvider: ImageDataProvider {
+
+    /// The possible error might be caused by the `PHPickerResultImageDataProvider`.
+    /// - invalidImage: The retrieved image is invalid.
+    public enum PHPickerResultImageDataProviderError: Error {
+        /// The retrieved image is invalid.
+        case invalidImage
+    }
+
+    /// The picker result bound to `self`.
+    public let pickerResult: PHPickerResult
+
+    /// The content type of the image.
+    public let contentType: UTType
+
+    private var internalKey: String {
+        pickerResult.assetIdentifier ?? UUID().uuidString
+    }
+
+    public var cacheKey: String {
+        "\(internalKey)_\(contentType.identifier)"
+    }
+
+    /// Creates an image data provider from a given `PHPickerResult`.
+    /// - Parameters:
+    ///  - pickerResult: The picker result to provide image data.
+    ///  - contentType: The content type of the image. Default is `UTType.image`.
+    public init(pickerResult: PHPickerResult, contentType: UTType = UTType.image) {
+        self.pickerResult = pickerResult
+        self.contentType = contentType
+    }
+
+    public func data(handler: @escaping (Result<Data, Error>) -> Void) {
+        pickerResult.itemProvider.loadDataRepresentation(forTypeIdentifier: contentType.identifier) { data, error in
+            if let error {
+                handler(.failure(error))
+                return
+            }
+
+            guard let data else {
+                handler(.failure(PHPickerResultImageDataProviderError.invalidImage))
+                return
+            }
+
+            handler(.success(data))
+        }
+    }
+}