浏览代码

Update doc

onevcat 1 年之前
父节点
当前提交
5387e7b3f1

+ 1 - 0
README.md

@@ -29,6 +29,7 @@ Kingfisher is a powerful, pure-Swift library for downloading and caching images
 - [x] Low Data Mode support.
 - [x] Low Data Mode support.
 - [x] SwiftUI support.
 - [x] SwiftUI support.
 - [x] Swift 6 & Swift Concurrency (strict mode) prepared.
 - [x] Swift 6 & Swift Concurrency (strict mode) prepared.
+- [x] Load & cache for Live Photo.
 
 
 ### Kingfisher 101
 ### Kingfisher 101
 
 

+ 17 - 9
Sources/Cache/DiskStorage.swift

@@ -284,9 +284,11 @@ public enum DiskStorage {
         }
         }
 
 
         /// Determines whether there is valid cached data under a given key.
         /// Determines whether there is valid cached data under a given key.
-        ///
-        /// - Parameter key: The cache key of the value.
-        /// - Returns: `true` if there is valid data under the key; otherwise, `false`.
+        /// 
+        /// - Parameters:
+        ///   - key: The cache key of the value.
+        ///   - forcedExtension: The file extension, if exists.
+        /// - Returns: `true` if there is valid data under the key and file extension; otherwise, `false`.
         ///
         ///
         /// > This method does not actually load the data from disk, so it is faster than directly loading the cached
         /// > This method does not actually load the data from disk, so it is faster than directly loading the cached
         /// value by checking the nullability of the ``DiskStorage/Backend/value(forKey:extendingExpiration:)`` method.
         /// value by checking the nullability of the ``DiskStorage/Backend/value(forKey:extendingExpiration:)`` method.
@@ -299,6 +301,7 @@ public enum DiskStorage {
         /// - Parameters:
         /// - Parameters:
         ///   - key: The cache key of the value.
         ///   - key: The cache key of the value.
         ///   - referenceDate: A reference date to check whether the cache is still valid.
         ///   - referenceDate: A reference date to check whether the cache is still valid.
+        ///   - forcedExtension: The file extension, if exists.
         ///
         ///
         /// - Returns: `true` if there is valid data under the key; otherwise, `false`.
         /// - Returns: `true` if there is valid data under the key; otherwise, `false`.
         ///
         ///
@@ -321,7 +324,9 @@ public enum DiskStorage {
         }
         }
 
 
         /// Removes a value from a specified key.
         /// Removes a value from a specified key.
-        /// - Parameter key: The cache key of the value.
+        /// - Parameters:
+        ///   - key: The cache key of the value.
+        ///   - forcedExtension: The file extension, if exists.
         /// - Throws: An error during the removal of the value.
         /// - Throws: An error during the removal of the value.
         public func remove(forKey key: String, forcedExtension: String? = nil) throws {
         public func remove(forKey key: String, forcedExtension: String? = nil) throws {
             let fileURL = cacheFileURL(forKey: key, forcedExtension: forcedExtension)
             let fileURL = cacheFileURL(forKey: key, forcedExtension: forcedExtension)
@@ -344,15 +349,18 @@ public enum DiskStorage {
                 try prepareDirectory()
                 try prepareDirectory()
             }
             }
         }
         }
-
+        
         /// The URL of the cached file with a given computed `key`.
         /// The URL of the cached file with a given computed `key`.
-        ///
-        /// - Parameter key: The final computed key used when caching the image. Please note that usually this is not
+        /// - Parameters:
+        ///   - key: The final computed key used when caching the image. Please note that usually this is not
         /// the ``Source/cacheKey`` of an image ``Source``. It is the computed key with the processor identifier
         /// the ``Source/cacheKey`` of an image ``Source``. It is the computed key with the processor identifier
         /// considered.
         /// considered.
+        ///   - forcedExtension: The file extension, if exists.
+        /// - Returns: The expected file URL on the disk based on the `key` and the `forcedExtension`.
+        ///
+        /// This method does not guarantee that an image is already cached at the returned URL. It just provides the URL
+        /// where the image should be if it exists in the disk storage, with the given key and file extension.
         ///
         ///
-        /// This method does not guarantee that an image is already cached at the returned URL. It just provides the URL 
-        /// where the image should be if it exists in the disk storage, with the given key.
         public func cacheFileURL(forKey key: String, forcedExtension: String? = nil) -> URL {
         public func cacheFileURL(forKey key: String, forcedExtension: String? = nil) -> URL {
             let fileName = cacheFileName(forKey: key, forcedExtension: forcedExtension)
             let fileName = cacheFileName(forKey: key, forcedExtension: forcedExtension)
             return directoryURL.appendingPathComponent(fileName, isDirectory: false)
             return directoryURL.appendingPathComponent(fileName, isDirectory: false)

+ 7 - 3
Sources/Documentation.docc/Documentation.md

@@ -1,4 +1,4 @@
-# Kingfisher
+# ``Kingfisher``
 
 
 @Metadata {
 @Metadata {
     @PageImage(
     @PageImage(
@@ -40,8 +40,7 @@ downloading again.
 ### Loading Images in Simple Way
 ### Loading Images in Simple Way
 
 
 - ``KingfisherCompatible``
 - ``KingfisherCompatible``
-- ``KingfisherWrapper/setImage(with:placeholder:options:completionHandler:)-2srsv``
-- ``KingfisherWrapper/setImage(with:placeholder:options:completionHandler:)-3ft7a``
+- ``KingfisherWrapper/setImage(with:placeholder:options:completionHandler:)-8qfkr``
 - ``KingfisherManager``
 - ``KingfisherManager``
 - ``Source``
 - ``Source``
 
 
@@ -75,6 +74,11 @@ downloading again.
 - ``AnimatedImageView``
 - ``AnimatedImageView``
 - ``GIFAnimatedImage``
 - ``GIFAnimatedImage``
 
 
+### Live Photo
+
+- <doc:Topic_LivePhoto>
+- ``KingfisherWrapper/setImage(with:options:completionHandler:)-1to8a``
+
 ### SwiftUI
 ### SwiftUI
 
 
 - ``KFImage``
 - ``KFImage``

+ 104 - 0
Sources/Documentation.docc/Topics/Topic_LivePhoto.md

@@ -0,0 +1,104 @@
+# Loading Live Photos
+
+Load and cache Live Photos from network sources using Kingfisher.
+
+## Overview
+
+Kingfisher provides a seamless way to load Live Photos, which consist of a still image and a video, from network sources. This guide will walk you through the process of utilizing Kingfisher's Live Photo support.
+
+## Live Photo Data Preparation
+
+Before loading a Live Photo with Kingfisher, you need to prepare and host the data. Kingfisher can download and cache the live photo data from the network (usually your server or a CDN). This section demonstrates how to get the necessary data from a `PHAsset`.
+
+If you've already set up the data and prepared the necessary URLs for the live photo components, you can skip to the next section to learn how to load it.
+
+Assuming you have a valid `PHAsset` from the Photos framework, here's a sample of how to extract its data:
+
+```swift
+let asset: PHAsset = // ... your PHAsset
+if !asset.mediaSubtypes.contains(.photoLive) {
+    print("Not a live photo")
+    return
+}
+
+let resources = PHAssetResource.assetResources(for: asset)
+var allData = [Data]()
+
+let group = DispatchGroup()
+group.notify(queue: .main) {
+    allData.forEach { data in
+        // Upload data to your server
+        serverRequest.upload(data)
+    }
+}
+
+resources.forEach { resource in
+    group.enter()
+    var data = Data()
+    PHAssetResourceManager.default().requestData(for: resource, options: nil) { chunk in
+        data.append(chunk)
+    } completionHandler: { error in
+        defer { group.leave() }
+        if let error = error {
+            print("Error: \(error)")
+            return
+        }
+        allData.append(data)
+    }
+}
+```
+
+Important notes:
+- This is a basic example showing how to retrieve data from a live photo asset.
+- Use [`PHAssetResource.type`]((https://developer.apple.com/documentation/photokit/phassetresource/1623987-type)) to get more information about each live photo resource. Typically, resources with `.photo` and `.pairedVideo` types are necessary for a minimal Live Photo.
+- Do not modify the metadata or actual data of the resources, as this may cause problems when loading in Kingfisher later.
+- When serving the files, it's recommended to include the file extensions (`.heic` for the still image, and `.mov` for the video) in the URL. While not mandatory, this helps Kingfisher identify the file type more accurately.
+- You can use [`PHAssetResource.originalFilename`](https://developer.apple.com/documentation/photokit/phassetresource/1623985-originalfilename) to get and preserve the original file extension.
+
+
+## Loading Live Photos
+
+### Step 1: Import Required Frameworks and Set Up PHLivePhotoView
+
+```swift
+import Kingfisher
+import PhotosUI
+
+let livePhotoView = PHLivePhotoView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
+view.addSubview(livePhotoView)
+```
+
+### Step 2: Prepare URLs
+
+```swift
+let imageURL = URL(string: "https://example.com/image.heic")!
+let videoURL = URL(string: "https://example.com/video.mov")!
+let urls = [imageURL, videoURL]
+```
+
+### Step 3: Load the Live Photo
+
+```swift
+livePhotoView.kf.setImage(with: urls) { result in
+    switch result {
+    case .success(let retrieveResult):
+        print("Live photo loaded: \(retrieveResult.livePhoto)")
+        print("Cache type: \(retrieveResult.loadingInfo.cacheType)")
+    case .failure(let error):
+        print("Error: \(error)")
+    }
+}
+```
+
+The loaded live photo will be stored in the disk cache of Kingfisher to boost future loading requests. 
+
+## Notes
+
+- Verify that the provided URLs are valid and accessible.
+- Loading may take time, especially for resources fetched over the network.
+- Certain `KingfisherOptionsInfo` options, such as custom processors, are not supported for Live Photos.
+- To load a Live Photo, its data must be cached on disk at least during the loading process. If you prefer not to retain the Live Photo data on disk, you can set a short disk cache expiration using options like `.diskCacheExpiration(.seconds(10))`, or manually clear the disk cache regularly after using.
+
+## Conclusion
+
+By following these steps, you can efficiently load and cache Live Photos in your iOS applications using Kingfisher, enhancing the user experience with smooth integration of this dynamic content type.

+ 1 - 1
Sources/Extensions/PHLivePhotoView+Kingfisher.swift

@@ -145,7 +145,7 @@ extension KingfisherWrapper where Base: PHLivePhotoView {
     ///
     ///
     /// - Parameters:
     /// - Parameters:
     ///   - source: The ``LivePhotoSource`` object defining the live photo resource.
     ///   - source: The ``LivePhotoSource`` object defining the live photo resource.
-    ///   - options: An options set to define image setting behaviors. See `KingfisherOptionsInfo` for more.
+    ///   - options: An options set to define image setting behaviors. See ``KingfisherOptionsInfo`` for more.
     ///   - completionHandler: Called when the image setting process finishes.
     ///   - completionHandler: Called when the image setting process finishes.
     /// - Returns: A task represents the image downloading.
     /// - Returns: A task represents the image downloading.
     ///            The return value will be `nil` if the image is set with a empty source.
     ///            The return value will be `nil` if the image is set with a empty source.