Skip to content

Commit

Permalink
Utilities/ImageTools (#327)
Browse files Browse the repository at this point in the history
  • Loading branch information
borut-t authored Nov 12, 2024
1 parent e59da27 commit a643c86
Show file tree
Hide file tree
Showing 8 changed files with 493 additions and 6 deletions.
3 changes: 3 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ let package = Package(
"PovioKitSwiftUI",
"PovioKitUtilities",
"PovioKitAsync",
],
resources: [
.process("Resources/")
]
),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public extension UnkeyedDecodingContainer {
// MARK: - Private Model
private struct AnyCodingKey: CodingKey {
let stringValue: String
private (set) var intValue: Int?
private(set) var intValue: Int?

init?(stringValue: String) { self.stringValue = stringValue }
init?(intValue: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ public extension View {
frame(width: size, height: size, alignment: alignment)
}

/// Returns square frame for given CGSize.
func frame(size: CGSize, alignment: Alignment = .center) -> some View {
frame(width: size.width, height: size.height, alignment: alignment)
}

/// Hides view using opacity.
func hidden(_ hidden: Bool) -> some View {
opacity(hidden ? 0 : 1)
Expand Down
114 changes: 114 additions & 0 deletions Sources/Core/Extensions/UIKit/UIImage+Kingfisher.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//
// File.swift
// PovioKit
//
// Created by Borut Tomazin on 26. 9. 24.
//

#if canImport(Kingfisher)
import UIKit
import Kingfisher

public extension UIImage {
struct PrefetchResult {
let skipped: Int
let failed: Int
let completed: Int
}

/// Downloads an image from the given URL asynchronously.
///
/// This function uses the Kingfisher library to download an image from the specified URL.
/// It performs the download operation asynchronously and returns the downloaded UIImage.
/// If the download operation fails, the function throws an error.
///
/// - Parameters:
/// - url: The URL from which to download the image.
/// - Returns: The downloaded UIImage.
///
/// - Example:
/// ```swift
/// do {
/// let url = URL(string: "https://example.com/image.jpg")!
/// let downloadedImage = try await UIImage.download(from: url)
/// imageView.image = downloadedImage
/// } catch {
/// Logger.error("Failed to download image: \(error)")
/// }
/// ```
///
/// - Note: This function should be called from an asynchronous context using `await`.
/// - Throws: An error if the download operation fails.
static func download(from url: URL) async throws -> UIImage {
try await withCheckedThrowingContinuation { continuation in
KingfisherManager.shared.retrieveImage(with: url, options: nil, progressBlock: nil, downloadTaskUpdated: nil) {
switch $0 {
case .success(let result):
continuation.resume(returning: result.image)
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}

/// Prefetches images from the given URLs asynchronously.
///
/// This function uses the Kingfisher library to prefetch images from the specified URLs.
/// It performs the prefetch operation asynchronously and returns a `PrefetchResult` containing
/// the counts of skipped, failed, and completed prefetch operations.
///
/// It is usefull when we need to have images ready before we present the UI.
///
/// - Parameters:
/// - urls: An array of URLs from which to prefetch images.
/// - Returns: A `PrefetchResult` containing the counts of skipped, failed, and completed prefetch operations.
///
/// - Example:
/// ```swift
/// let urls = [
/// URL(string: "https://example.com/image1.jpg")!,
/// URL(string: "https://example.com/image2.jpg")!
/// ]
/// let result = await UIImage.prefetch(urls: urls)
/// Logger.info("Skipped: \(result.skipped), Failed: \(result.failed), Completed: \(result.completed)")
/// ```
///
/// - Note: This function should be called from an asynchronous context using `await`.
@discardableResult
static func prefetch(from urls: [URL]) async -> PrefetchResult {
await withCheckedContinuation { continuation in
let prefetcher = ImagePrefetcher(urls: urls, options: nil) { skipped, failed, completed in
let result = PrefetchResult(
skipped: skipped.count,
failed: failed.count,
completed: completed.count
)
continuation.resume(with: .success(result))
}
prefetcher.start()
}
}

/// Clears the image cache.
///
/// This function clears the image cache using the specified ImageCache instance.
/// If no cache instance is provided, it defaults to using the shared cache of the KingfisherManager.
///
/// - Parameters:
/// - cache: The ImageCache instance to be cleared. Defaults to `KingfisherManager.shared.cache`.
///
/// - Example:
/// ```swift
/// // Clear the default shared cache
/// UIImage.clearCache()
///
/// // Clear a specific cache instance
/// let customCache = ImageCache(name: "customCache")
/// UIImage.clearCache(customCache)
/// ```
public static func clearCache(_ cache: ImageCache = KingfisherManager.shared.cache) {
cache.clearCache()
}
}
#endif
Loading

0 comments on commit a643c86

Please sign in to comment.