Skip to content

Commit

Permalink
Update doc
Browse files Browse the repository at this point in the history
  • Loading branch information
onevcat committed Oct 12, 2024
1 parent a5a67c6 commit 5387e7b
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 13 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Kingfisher is a powerful, pure-Swift library for downloading and caching images
- [x] Low Data Mode support.
- [x] SwiftUI support.
- [x] Swift 6 & Swift Concurrency (strict mode) prepared.
- [x] Load & cache for Live Photo.

### Kingfisher 101

Expand Down
26 changes: 17 additions & 9 deletions Sources/Cache/DiskStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,11 @@ public enum DiskStorage {
}

/// 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
/// value by checking the nullability of the ``DiskStorage/Backend/value(forKey:extendingExpiration:)`` method.
Expand All @@ -299,6 +301,7 @@ public enum DiskStorage {
/// - Parameters:
/// - key: The cache key of the value.
/// - 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`.
///
Expand All @@ -321,7 +324,9 @@ public enum DiskStorage {
}

/// 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.
public func remove(forKey key: String, forcedExtension: String? = nil) throws {
let fileURL = cacheFileURL(forKey: key, forcedExtension: forcedExtension)
Expand All @@ -344,15 +349,18 @@ public enum DiskStorage {
try prepareDirectory()
}
}

/// 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
/// 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 {
let fileName = cacheFileName(forKey: key, forcedExtension: forcedExtension)
return directoryURL.appendingPathComponent(fileName, isDirectory: false)
Expand Down
10 changes: 7 additions & 3 deletions Sources/Documentation.docc/Documentation.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Kingfisher
# ``Kingfisher``

@Metadata {
@PageImage(
Expand Down Expand Up @@ -40,8 +40,7 @@ downloading again.
### Loading Images in Simple Way

- ``KingfisherCompatible``
- ``KingfisherWrapper/setImage(with:placeholder:options:completionHandler:)-2srsv``
- ``KingfisherWrapper/setImage(with:placeholder:options:completionHandler:)-3ft7a``
- ``KingfisherWrapper/setImage(with:placeholder:options:completionHandler:)-8qfkr``
- ``KingfisherManager``
- ``Source``

Expand Down Expand Up @@ -75,6 +74,11 @@ downloading again.
- ``AnimatedImageView``
- ``GIFAnimatedImage``

### Live Photo

- <doc:Topic_LivePhoto>
- ``KingfisherWrapper/setImage(with:options:completionHandler:)-1to8a``

### SwiftUI

- ``KFImage``
Expand Down
104 changes: 104 additions & 0 deletions Sources/Documentation.docc/Topics/Topic_LivePhoto.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion Sources/Extensions/PHLivePhotoView+Kingfisher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ extension KingfisherWrapper where Base: PHLivePhotoView {
///
/// - Parameters:
/// - 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.
/// - Returns: A task represents the image downloading.
/// The return value will be `nil` if the image is set with a empty source.
Expand Down

0 comments on commit 5387e7b

Please sign in to comment.