Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nuke 12.6 #777

Merged
merged 38 commits into from
Apr 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
3e9d0bd
Rework task reuse in TaskLoadImage
kean Apr 20, 2024
1791c1a
Reduce number of testLoadWithInvalidURL tests
kean Apr 20, 2024
2728c10
Fix redundant decompressions
kean Apr 20, 2024
9591857
testWhenApplingMultipleImageProcessorsIntermediateDataCacheResultsAre…
kean Apr 20, 2024
07e57b3
Remove AsyncTask.dependency2
kean Apr 20, 2024
cd0fb59
Remove OperationTask
kean Apr 20, 2024
fc6b582
Disable testDecompressionSkippedIfProcessorsAreApplied on macOS where…
kean Apr 20, 2024
b8195fb
Update ci.yml to use latest Xcode
kean Apr 20, 2024
0046839
Disable flaky _testProgressUpdated
kean Apr 20, 2024
17cbd6c
Fix tests with invalid URL
kean Apr 20, 2024
5bf0fe8
Update tests
kean Apr 20, 2024
e20f644
Deprecated ImagePipeline.Configuration.dataCachingQueue
kean Apr 20, 2024
1422578
Reuse image decoding code
kean Apr 20, 2024
a1a640b
Cleanup TaskLoadImage
kean Apr 20, 2024
bafe72c
Skip decompression for .png images
kean Apr 20, 2024
38672c0
Cleanup shouldStoreResponseInDataCache
kean Apr 20, 2024
735dde3
Cleanup isEphemeral
kean Apr 20, 2024
01f2217
Optmize shouldStoreDataInDiskCache
kean Apr 20, 2024
192964e
Fix an issue where original data was stored using the thumbnail optio…
kean Apr 20, 2024
2b55252
Fix an issue with scale and coalesing
kean Apr 20, 2024
8be9080
Fix onStart
kean Apr 20, 2024
ef06d3a
Add support for initializing ImageProcessors.CoreImageFilter with CIF…
kean Apr 20, 2024
648d66d
Bring back compatibility with earlier Xcode verions
kean Apr 20, 2024
e98cc61
Fix build on macOS
kean Apr 21, 2024
ac674f3
Fix build on earlier macOS versions
kean Apr 21, 2024
a8d7e30
Fix typos
kean Apr 21, 2024
1b75c28
Cleanup TaskLoadImage
kean Apr 21, 2024
cd3e07e
Cleanup OSLog extensions
kean Apr 21, 2024
7d7efed
Enoder to return nil instead of an empty data if encoding fails
kean Apr 21, 2024
1f1fc21
Cleanup ImageRequestKeys
kean Apr 21, 2024
3b513dd
Avoid bridge to CFMutableData in ImageEncoders.ImageIO
kean Apr 21, 2024
fe38f1e
Re-enable tests
kean Apr 21, 2024
3776cae
Optimize TaskLoadImageKey
kean Apr 21, 2024
e4d214f
Fix flaky testCancelAsyncImageTask
kean Apr 21, 2024
c467c95
Update README
kean Apr 21, 2024
b0f29e8
Update task names
kean Apr 21, 2024
6a0a824
Add note about deprecation date
kean Apr 21, 2024
dbb4e99
Remove unused decoder parameter
kean Apr 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ on:

jobs:
ios-latest:
name: Unit Tests (iOS 16.4, Xcode 14.3.1)
runs-on: macOS-13
name: Unit Tests (iOS 17.4, Xcode 15.3)
runs-on: macOS-14
env:
DEVELOPER_DIR: /Applications/Xcode_14.3.1.app/Contents/Developer
DEVELOPER_DIR: /Applications/Xcode_15.3.app/Contents/Developer
steps:
- uses: actions/checkout@v2
- name: Run Tests
run: |
Scripts/test.sh -s "Nuke" -d "OS=16.4,name=iPhone 14 Pro"
Scripts/test.sh -s "NukeUI" -d "OS=16.4,name=iPhone 14 Pro"
Scripts/test.sh -s "NukeExtensions" -d "OS=16.4,name=iPhone 14 Pro"
Scripts/test.sh -s "Nuke" -d "OS=17.4,name=iPhone 15 Pro"
Scripts/test.sh -s "NukeUI" -d "OS=17.4,name=iPhone 15 Pro"
Scripts/test.sh -s "NukeExtensions" -d "OS=17.4,name=iPhone 15 Pro"
macos-latest:
name: Unit Tests (macOS, Xcode 14.3.1)
runs-on: macOS-13
env:
DEVELOPER_DIR: /Applications/Xcode_14.3.1.app/Contents/Developer
name: Unit Tests (macOS, Xcode 15.3)
runs-on: macOS-14
env:
DEVELOPER_DIR: /Applications/Xcode_15.3.app/Contents/Developer
steps:
- uses: actions/checkout@v2
- name: Run Tests
Expand All @@ -34,17 +34,17 @@ jobs:
Scripts/test.sh -s "NukeUI" -d "platform=macOS"
Scripts/test.sh -s "NukeExtensions" -d "platform=macOS"
tvos-latest:
name: Unit Tests (tvOS 16.4, Xcode 14.3.1)
runs-on: macOS-13
env:
DEVELOPER_DIR: /Applications/Xcode_14.3.1.app/Contents/Developer
name: Unit Tests (tvOS 17.4, Xcode 15.3)
runs-on: macOS-14
env:
DEVELOPER_DIR: /Applications/Xcode_15.3.app/Contents/Developer
steps:
- uses: actions/checkout@v2
- name: Run Tests
run: |
Scripts/test.sh -s "Nuke" -d "OS=16.4,name=Apple TV"
Scripts/test.sh -s "NukeUI" -d "OS=16.4,name=Apple TV"
Scripts/test.sh -s "NukeExtensions" -d "OS=16.4,name=Apple TV"
Scripts/test.sh -s "Nuke" -d "OS=17.4,name=Apple TV"
Scripts/test.sh -s "NukeUI" -d "OS=17.4,name=Apple TV"
Scripts/test.sh -s "NukeExtensions" -d "OS=17.4,name=Apple TV"
# There is a problem with watchOS runners where they often fail to launch on CI
#
# watchos-latest:
Expand All @@ -59,27 +59,27 @@ jobs:
# Scripts/test.sh -s "Nuke" -d "OS=9.1,name=Apple Watch Series 8 (45mm)"
# Scripts/test.sh -s "NukeUI" -d "OS=9.1,name=Apple Watch Series 8 (45mm)"
# Scripts/test.sh -s "Nuke Extensions" -d "OS=9.1,name=Apple Watch Series 8 (45mm)"
ios-xcode-14-1:
name: Unit Tests (iOS 16.1, Xcode 14.1)
ios-xcode-14-3-1:
name: Unit Tests (iOS 16.4, Xcode 14.3.1)
runs-on: macOS-13
env:
DEVELOPER_DIR: /Applications/Xcode_14.1.app/Contents/Developer
DEVELOPER_DIR: /Applications/Xcode_14.3.1.app/Contents/Developer
steps:
- uses: actions/checkout@v2
- name: Run Tests
run: |
Scripts/test.sh -s "Nuke" -d "OS=16.1,name=iPhone 14 Pro"
Scripts/test.sh -s "NukeUI" -d "OS=16.1,name=iPhone 14 Pro"
Scripts/test.sh -s "NukeExtensions" -d "OS=16.1,name=iPhone 14 Pro"
Scripts/test.sh -s "Nuke" -d "OS=16.4,name=iPhone 14 Pro"
Scripts/test.sh -s "NukeUI" -d "OS=16.4,name=iPhone 14 Pro"
Scripts/test.sh -s "NukeExtensions" -d "OS=16.4,name=iPhone 14 Pro"
ios-thread-safety:
name: Thread Safety Tests (TSan Enabled)
runs-on: macOS-13
env:
DEVELOPER_DIR: /Applications/Xcode_14.3.1.app/Contents/Developer
runs-on: macOS-14
env:
DEVELOPER_DIR: /Applications/Xcode_15.3.app/Contents/Developer
steps:
- uses: actions/checkout@v2
- name: Run Tests
run: Scripts/test.sh -s "Nuke Thread Safety Tests" -d "OS=16.4,name=iPhone 14 Pro"
run: Scripts/test.sh -s "Nuke Thread Safety Tests" -d "OS=17.4,name=iPhone 15 Pro"
# ios-memory-management-tests:
# name: Memory Management Tests
# runs-on: macOS-13
Expand Down
20 changes: 8 additions & 12 deletions Nuke.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@
0C8D7BED1D9DC02B00D12EB7 /* Nuke.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9174901BAE99EE004A7905 /* Nuke.framework */; };
0C8D7BF51D9DC07E00D12EB7 /* DataCachePeformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C8D74201D9D6EEB0036349E /* DataCachePeformanceTests.swift */; };
0C8DC723209B842600084AA6 /* cat.gif in Resources */ = {isa = PBXBuildFile; fileRef = 0C8DC722209B842600084AA6 /* cat.gif */; };
0C9165E626431942006B1D4F /* OperationTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C9165E526431942006B1D4F /* OperationTask.swift */; };
0C91B0EC2438E287007F9100 /* ResizeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C91B0EB2438E287007F9100 /* ResizeTests.swift */; };
0C91B0EE2438E307007F9100 /* CircleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C91B0ED2438E307007F9100 /* CircleTests.swift */; };
0C91B0F02438E352007F9100 /* RoundedCornersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C91B0EF2438E352007F9100 /* RoundedCornersTests.swift */; };
Expand Down Expand Up @@ -200,8 +199,8 @@
0CB26807208F25C2004C83F4 /* DataCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB26806208F25C2004C83F4 /* DataCacheTests.swift */; };
0CB2EFD22110F38600F7C63F /* ImagePipelineConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB2EFD12110F38600F7C63F /* ImagePipelineConfigurationTests.swift */; };
0CB2EFD62110F52C00F7C63F /* RateLimiterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB2EFD52110F52C00F7C63F /* RateLimiterTests.swift */; };
0CB402D525B6569700F5A241 /* TaskFetchOriginalImageData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB402D425B6569700F5A241 /* TaskFetchOriginalImageData.swift */; };
0CB402DB25B656D200F5A241 /* TaskFetchDecodedImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB402DA25B656D200F5A241 /* TaskFetchDecodedImage.swift */; };
0CB402D525B6569700F5A241 /* TaskFetchOriginalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB402D425B6569700F5A241 /* TaskFetchOriginalData.swift */; };
0CB402DB25B656D200F5A241 /* TaskFetchOriginalImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB402DA25B656D200F5A241 /* TaskFetchOriginalImage.swift */; };
0CB4030125B6639200F5A241 /* TaskLoadImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB4030025B6639200F5A241 /* TaskLoadImage.swift */; };
0CB6448928567DC300916267 /* MockImageProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C7C068A1BCA888800089D7F /* MockImageProcessor.swift */; };
0CB6448A28567DC300916267 /* MockDataLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C7C068C1BCA888800089D7F /* MockDataLoader.swift */; };
Expand Down Expand Up @@ -447,7 +446,6 @@
0C8D7BDE1D9DBF1600D12EB7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0C8D7BE81D9DC02B00D12EB7 /* Nuke Performance Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Nuke Performance Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
0C8DC722209B842600084AA6 /* cat.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = cat.gif; sourceTree = "<group>"; };
0C9165E526431942006B1D4F /* OperationTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationTask.swift; sourceTree = "<group>"; };
0C9174901BAE99EE004A7905 /* Nuke.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nuke.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0C91B0EB2438E287007F9100 /* ResizeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResizeTests.swift; sourceTree = "<group>"; };
0C91B0ED2438E307007F9100 /* CircleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -495,8 +493,8 @@
0CB26806208F25C2004C83F4 /* DataCacheTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataCacheTests.swift; sourceTree = "<group>"; };
0CB2EFD12110F38600F7C63F /* ImagePipelineConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePipelineConfigurationTests.swift; sourceTree = "<group>"; };
0CB2EFD52110F52C00F7C63F /* RateLimiterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RateLimiterTests.swift; sourceTree = "<group>"; };
0CB402D425B6569700F5A241 /* TaskFetchOriginalImageData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskFetchOriginalImageData.swift; sourceTree = "<group>"; };
0CB402DA25B656D200F5A241 /* TaskFetchDecodedImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskFetchDecodedImage.swift; sourceTree = "<group>"; };
0CB402D425B6569700F5A241 /* TaskFetchOriginalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskFetchOriginalData.swift; sourceTree = "<group>"; };
0CB402DA25B656D200F5A241 /* TaskFetchOriginalImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskFetchOriginalImage.swift; sourceTree = "<group>"; };
0CB4030025B6639200F5A241 /* TaskLoadImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskLoadImage.swift; sourceTree = "<group>"; };
0CB6449928567DE000916267 /* NukeExtensionsTestsHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NukeExtensionsTestsHelpers.swift; sourceTree = "<group>"; };
0CB6449B28567E5400916267 /* ImageViewLoadingOptionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewLoadingOptionsTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -971,10 +969,9 @@
0C2CD6EA25B67FB30017018F /* ImagePipelineTask.swift */,
0CB4030025B6639200F5A241 /* TaskLoadImage.swift */,
0C2A368A26437BF100F1D000 /* TaskLoadData.swift */,
0CB402DA25B656D200F5A241 /* TaskFetchDecodedImage.swift */,
0CB402D425B6569700F5A241 /* TaskFetchOriginalImageData.swift */,
0CB402DA25B656D200F5A241 /* TaskFetchOriginalImage.swift */,
0CB402D425B6569700F5A241 /* TaskFetchOriginalData.swift */,
0CE6202226543B6A00AAB8C3 /* TaskFetchWithPublisher.swift */,
0C9165E526431942006B1D4F /* OperationTask.swift */,
);
path = Tasks;
sourceTree = "<group>";
Expand Down Expand Up @@ -1731,12 +1728,11 @@
0CA4ECD026E68FC000BAC8E5 /* DataCaching.swift in Sources */,
0CA4ECCA26E6868300BAC8E5 /* ImageProcessingOptions.swift in Sources */,
0C53C8B1263C968200E62D03 /* ImagePipelineDelegate.swift in Sources */,
0C9165E626431942006B1D4F /* OperationTask.swift in Sources */,
0CA4ECBC26E6856300BAC8E5 /* ImageDecompression.swift in Sources */,
0CA4ECD326E68FDC00BAC8E5 /* ImageCaching.swift in Sources */,
0CA4ECC026E685C900BAC8E5 /* ImageProcessors+Anonymous.swift in Sources */,
0CA4ECC826E6864D00BAC8E5 /* ImageProcessors+RoundedCorners.swift in Sources */,
0CB402DB25B656D200F5A241 /* TaskFetchDecodedImage.swift in Sources */,
0CB402DB25B656D200F5A241 /* TaskFetchOriginalImage.swift in Sources */,
0C472F842654AD88007FC0F0 /* ImageRequestKeys.swift in Sources */,
0CE6202126542F7200AAB8C3 /* DataPublisher.swift in Sources */,
0CB0479A2856D9AC00DF9B6D /* Cache.swift in Sources */,
Expand All @@ -1763,7 +1759,7 @@
0CA4ECBE26E685A900BAC8E5 /* ImageProcessors+Circle.swift in Sources */,
0CE2D9BA2084FDDD00934B28 /* ImageDecoding.swift in Sources */,
0CC36A1925B8BC2500811018 /* RateLimiter.swift in Sources */,
0CB402D525B6569700F5A241 /* TaskFetchOriginalImageData.swift in Sources */,
0CB402D525B6569700F5A241 /* TaskFetchOriginalData.swift in Sources */,
0CA4ECAD26E683E300BAC8E5 /* ImageEncoders.swift in Sources */,
0CA4ECC626E6862A00BAC8E5 /* ImageProcessors+CoreImage.swift in Sources */,
0C2CD6EB25B67FB30017018F /* ImagePipelineTask.swift in Sources */,
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ Nuke supports [Swift Package Manager](https://www.swift.org/package-manager/), w

## Documentation

Nuke is easy to learn and use thanks to an extensive documentation. The best place to start is the [**Getting Started**](https://kean-docs.github.io/nuke/documentation/nuke/getting-started/) guide.
Nuke is easy to learn and use, thanks to its extensive documentation. The [**Getting Started**](https://kean-docs.github.io/nuke/documentation/nuke/getting-started/) guide is the best place to start learning how to use it.

Nuke package ships with four modules that you can install depending on your needs:
The package ships with four modules that you can install depending on your needs:

|Module|Description|
|--|--|
Expand All @@ -45,7 +45,7 @@ Nuke package ships with four modules that you can install depending on your need
|[**NukeExtensions**](https://kean-docs.github.io/nukeextensions/documentation/nukeextensions/)|The extensions for `UIImageView` (UIKit, AppKit)|
|[**NukeVideo**](https://kean-docs.github.io/nukevideo/documentation/nukevideo/)|The components for decoding and playing short videos|

To see more usage examples, check out [**Nuke Demo**](https://github.com/kean/NukeDemo).
Check out [**Nuke Demo**](https://github.com/kean/NukeDemo) for more usage examples.

> Upgrading from the previous version? Use a [**Migration Guide**](https://github.com/kean/Nuke/tree/master/Documentation/Migrations).

Expand Down
4 changes: 2 additions & 2 deletions Sources/Nuke/Caching/ImageCaching.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ public struct ImageCacheKey: Hashable, Sendable {
// This is faster than using AnyHashable (and it shows in performance tests).
enum Inner: Hashable, Sendable {
case custom(String)
case `default`(CacheKey)
case `default`(MemoryCacheKey)
}

public init(key: String) {
self.key = .custom(key)
}

public init(request: ImageRequest) {
self.key = .default(request.makeImageCacheKey())
self.key = .default(MemoryCacheKey(request))
}
}
14 changes: 8 additions & 6 deletions Sources/Nuke/Encoding/ImageEncoders+ImageIO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,21 @@ extension ImageEncoders {
}

public func encode(_ image: PlatformImage) -> Data? {
let data = NSMutableData()
guard let source = image.cgImage,
let data = CFDataCreateMutable(nil, 0),
let destination = CGImageDestinationCreateWithData(data, type.rawValue as CFString, 1, nil) else {
return nil
}
var options: [CFString: Any] = [
kCGImageDestinationLossyCompressionQuality: compressionRatio
]
#if canImport(UIKit)
options[kCGImagePropertyOrientation] = CGImagePropertyOrientation(image.imageOrientation).rawValue
#endif
guard let source = image.cgImage,
let destination = CGImageDestinationCreateWithData(data as CFMutableData, type.rawValue as CFString, 1, nil) else {
return nil
}
CGImageDestinationAddImage(destination, source, options as CFDictionary)
CGImageDestinationFinalize(destination)
guard CGImageDestinationFinalize(destination) else {
return nil
}
return data as Data
}
}
Expand Down
89 changes: 27 additions & 62 deletions Sources/Nuke/Internal/ImageRequestKeys.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,98 +4,73 @@

import Foundation

extension ImageRequest {

// MARK: - Cache Keys

/// A key for processed image in memory cache.
func makeImageCacheKey() -> CacheKey {
CacheKey(self)
}

/// A key for processed image data in disk cache.
func makeDataCacheKey() -> String {
"\(preferredImageId)\(thumbnail?.identifier ?? "")\(ImageProcessors.Composition(processors).identifier)"
}

// MARK: - Load Keys

/// A key for deduplicating operations for fetching the processed image.
func makeImageLoadKey() -> ImageLoadKey {
ImageLoadKey(self)
}

/// A key for deduplicating operations for fetching the decoded image.
func makeDecodedImageLoadKey() -> DecodedImageLoadKey {
DecodedImageLoadKey(self)
}

/// A key for deduplicating operations for fetching the original image.
func makeDataLoadKey() -> DataLoadKey {
DataLoadKey(self)
}
}

/// Uniquely identifies a cache processed image.
final class CacheKey: Hashable, Sendable {
final class MemoryCacheKey: Hashable, Sendable {
// Using a reference type turned out to be significantly faster
private let imageId: String?
private let scale: Float
private let thumbnail: ImageRequest.ThumbnailOptions?
private let processors: [any ImageProcessing]

init(_ request: ImageRequest) {
self.imageId = request.preferredImageId
self.scale = request.scale ?? 1
self.thumbnail = request.thumbnail
self.processors = request.processors
}

func hash(into hasher: inout Hasher) {
hasher.combine(imageId)
hasher.combine(scale)
hasher.combine(thumbnail)
hasher.combine(processors.count)
}

static func == (lhs: CacheKey, rhs: CacheKey) -> Bool {
lhs.imageId == rhs.imageId && lhs.thumbnail == rhs.thumbnail && lhs.processors == rhs.processors
static func == (lhs: MemoryCacheKey, rhs: MemoryCacheKey) -> Bool {
lhs.imageId == rhs.imageId && lhs.scale == rhs.scale && lhs.thumbnail == rhs.thumbnail && lhs.processors == rhs.processors
}
}

// MARK: - Identifying Tasks

/// Uniquely identifies a task of retrieving the processed image.
final class ImageLoadKey: Hashable, Sendable {
let cacheKey: CacheKey
let options: ImageRequest.Options
let loadKey: DataLoadKey
final class TaskLoadImageKey: Hashable, Sendable {
private let loadKey: TaskFetchOriginalImageKey
private let options: ImageRequest.Options
private let processors: [any ImageProcessing]

init(_ request: ImageRequest) {
self.cacheKey = CacheKey(request)
self.loadKey = TaskFetchOriginalImageKey(request)
self.options = request.options
self.loadKey = DataLoadKey(request)
self.processors = request.processors
}

func hash(into hasher: inout Hasher) {
hasher.combine(cacheKey.hashValue)
hasher.combine(options.hashValue)
hasher.combine(loadKey.hashValue)
hasher.combine(options.hashValue)
hasher.combine(processors.count)
}

static func == (lhs: ImageLoadKey, rhs: ImageLoadKey) -> Bool {
lhs.cacheKey == rhs.cacheKey && lhs.options == rhs.options && lhs.loadKey == rhs.loadKey
static func == (lhs: TaskLoadImageKey, rhs: TaskLoadImageKey) -> Bool {
lhs.loadKey == rhs.loadKey && lhs.options == rhs.options && lhs.processors == rhs.processors
}
}

/// Uniquely identifies a task of retrieving the decoded image.
struct DecodedImageLoadKey: Hashable {
let dataLoadKey: DataLoadKey
let thumbnail: ImageRequest.ThumbnailOptions?
/// Uniquely identifies a task of retrieving the original image.
struct TaskFetchOriginalImageKey: Hashable {
private let dataLoadKey: TaskFetchOriginalDataKey
private let scale: Float
private let thumbnail: ImageRequest.ThumbnailOptions?

init(_ request: ImageRequest) {
self.dataLoadKey = DataLoadKey(request)
self.dataLoadKey = TaskFetchOriginalDataKey(request)
self.scale = request.scale ?? 1
self.thumbnail = request.thumbnail
}
}

/// Uniquely identifies a task of retrieving the original image dataa.
struct DataLoadKey: Hashable {
/// Uniquely identifies a task of retrieving the original image data.
struct TaskFetchOriginalDataKey: Hashable {
private let imageId: String?
private let cachePolicy: URLRequest.CachePolicy
private let allowsCellularAccess: Bool
Expand All @@ -112,13 +87,3 @@ struct DataLoadKey: Hashable {
}
}
}

struct ImageProcessingKey: Equatable, Hashable {
let imageId: ObjectIdentifier
let processorId: AnyHashable

init(image: ImageResponse, processor: any ImageProcessing) {
self.imageId = ObjectIdentifier(image.image)
self.processorId = processor.hashableIdentifier
}
}
Loading
Loading