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 13 – Swift 6 #802

Open
wants to merge 136 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
cc2789f
Add ImagePipelineActor
kean Jul 28, 2024
ed5ae0b
Remove deprecated APIs from ImagePipeleine
kean Jul 28, 2024
d122647
Remove AsyncImageTask
kean Jul 28, 2024
3ce7e92
Remove ImagePipeline.Configuration.callbackQueue parameter
kean Jul 28, 2024
8422630
Add a note about ImagePipeline.Configuration
kean Jul 28, 2024
1a469cb
Remove onTaskCreated tests – this situation was eliminated
kean Jul 28, 2024
e793012
Safer testLoadDataDataLoaded
kean Jul 28, 2024
b72c56b
Add ImagePublisher back
kean Jul 28, 2024
8c6f7f2
Use Atomic for ImageTaskNonisolatedState
kean Jul 28, 2024
786bebc
Cleanup
kean Jul 28, 2024
6168ab1
Remove deprecated APIs
kean Jul 28, 2024
4b2f473
Update unit tests
kean Aug 3, 2024
287b1db
Rename Atomic to Mutex
kean Aug 3, 2024
f07a2e1
Make some of ImageTask properties nonislated
kean Aug 3, 2024
5a0c759
Make ImageTask/continuation private
kean Aug 3, 2024
8983d5d
Make ImageTask.State explicitly Sendable
kean Aug 3, 2024
796f5c6
Rework isolation in ImageTask
kean Aug 17, 2024
039b163
Remove nonisolated ImageTask.state
kean Aug 17, 2024
109621c
Remove ImageTaskExecutionContext
kean Aug 17, 2024
00d6f18
Cleanup ImageTask
kean Aug 17, 2024
a774d51
Revert imageTaskCreated removal
kean Aug 17, 2024
4b21e2e
Revert imageTaskCreated removal
kean Aug 17, 2024
c56dbae
Remove soft-deprecated APIs from ImagePipeline.Delegate
kean Aug 17, 2024
45c7fd6
Rename ImagePipelineDelegate to ImagePipeline.Delegate
kean Aug 17, 2024
a2bd2f7
Move Combine extensions
kean Aug 17, 2024
351be3a
Remove DataPublisher support
kean Aug 17, 2024
836cf75
Update warnings
kean Aug 17, 2024
f742a0c
Update DataLoading protocol to use Swift Concurrency
kean Aug 17, 2024
f4a4b74
Update ResumableDataStore to use generic namespace ID
kean Aug 17, 2024
a43d235
Revert DataLoader to use URLRequest as parameter for now
kean Aug 17, 2024
8befa46
Reimplement data loading with closure
kean Aug 18, 2024
2306a4e
Update ImagePrefetcher to use Swift Concurrency (partially)
kean Aug 18, 2024
83dc0eb
Update ImagePipeline callbacks to be main actor isolated
kean Aug 18, 2024
b8d190d
Remove UncheckedSendableBox
kean Aug 18, 2024
d650baf
Remove now redundant _loadData method
kean Aug 18, 2024
70b92f0
Fix a concurrency warning in RateLimiter
kean Aug 18, 2024
123586a
Fix RateLimiter tests
kean Aug 18, 2024
38dc11c
Remove one of the loadData variant
kean Aug 18, 2024
2e0e6b6
Rename makeImageTask
kean Aug 18, 2024
1b7547a
Rename imageTaskUpdatePriorityCalled
kean Aug 18, 2024
7e34b50
Soft-deprecate closure-based APIs
kean Aug 18, 2024
97c3ccd
Remove warning in isResumableDataEnabled
kean Aug 18, 2024
cd82f34
Remove Sendable conformance from AsyncPipelineTask
kean Aug 18, 2024
868da19
Remove unused isResumableDataEnabled
kean Aug 18, 2024
84400f0
Remove redundant @unchecked from ImageProcessingOptions.Border
kean Aug 18, 2024
0e5273b
Remove redundant @unchecked Sendable
kean Aug 18, 2024
8ab81b7
Update ImagePrefetcher
kean Oct 26, 2024
1c495bd
Update TaskTests
kean Oct 26, 2024
6df73d2
Update testCancelAsyncImageTask
kean Oct 26, 2024
6dadf6e
Simplify didComplete
kean Oct 26, 2024
3fbd5b0
Deprecate FetchImage.load with Publisher
kean Oct 26, 2024
2086dc6
Update tests
kean Oct 26, 2024
bf79725
Fix an issue with state being writable
kean Oct 27, 2024
bca4607
Sync ImageTask on ImagePipelineActor
kean Oct 27, 2024
b620989
Update how withLock is used
kean Oct 27, 2024
81e8412
ImageRequest.Container is no longer Sendable
kean Oct 27, 2024
072f732
Update ci.yml
kean Oct 27, 2024
9c025c6
Update performance tests
kean Oct 27, 2024
a4413f6
Bump macOS deployment target to macOS 11
kean Oct 27, 2024
de39ec1
Increase deployment targets
kean Oct 27, 2024
4878846
Remove @unchecked from ImagePipeline.Error Sendable conformance
kean Oct 27, 2024
2896769
Fix SwiftPM build on macOS
kean Nov 17, 2024
7e684d1
Add retroactive conformances in test targets
kean Nov 17, 2024
ef82a7d
Enable Swift 6
kean Nov 17, 2024
bec2101
Update RateLimiterTests to swift-testing
kean Nov 17, 2024
26487ea
Use expect instead of require
kean Nov 17, 2024
9f7eb9c
Enable complete concurrency checking in unit tests
kean Nov 17, 2024
13d363e
Update TaskTests
kean Nov 17, 2024
52771a0
Update ImageRequestTests
kean Nov 17, 2024
4e0bca9
Update ImageCacheTests
kean Nov 17, 2024
b62cc43
Update ImageDecoderTests
kean Nov 17, 2024
f9438e3
Update ImageDecoderRegistryTests
kean Nov 17, 2024
056d66f
Update ImageEncoderTests
kean Nov 17, 2024
5abfe24
Update some of the ImagePrefetcher tests
kean Jan 1, 2025
dfd86bd
Update copyright
kean Jan 1, 2025
890cd3b
Fix releaes notes
kean Jan 1, 2025
c364bc0
Add initial TaskQueue implementation
kean Jan 2, 2025
03c2fe2
Skip pendingTasks when possible
kean Jan 2, 2025
8e5d1ac
Make ScheduledTask private
kean Jan 2, 2025
ddcce7b
Fix formatting
kean Jan 2, 2025
f3cda93
Add cancelInFlightWork
kean Jan 2, 2025
caf48a8
Add support for cancelling pending tasks
kean Jan 2, 2025
59d43d7
Rename WorkQueue
kean Jan 2, 2025
1eb3e9f
Move WorkQueue to Internal
kean Jan 2, 2025
2004bfc
Add basic support for priorities in WorkQueue
kean Jan 2, 2025
9bed910
Add support for dynamically changing priority of work items
kean Jan 4, 2025
c9a4945
Add a convenience API for enqueuing work
kean Jan 4, 2025
c588953
Eagerly pop cancelled items from the queue
kean Jan 4, 2025
2b966b2
Integrate WorkQueue in ImagePrefetcher
kean Jan 4, 2025
b130abf
Add initial AsyncExpectation implementation
kean Jan 4, 2025
95671fc
Rewrite AsyncExpectation using Mutex
kean Jan 4, 2025
e646495
Fix WorkQueue not retaining WorkItem
kean Jan 4, 2025
67033d2
Update cancelInFlightWork to not require Work.Item init
kean Jan 4, 2025
d6db94f
Update WorkQueue API to not expose WorkItem int
kean Jan 4, 2025
cfd4014
Ensure retaing WorkQueue.Item never leads to retain cycles
kean Jan 4, 2025
34b3604
Add support for pausing the prefetcher
kean Jan 4, 2025
0483c5a
Fix an issue with ImagePrefetcher not deallocating in case there are …
kean Jan 5, 2025
b255543
Replace dataLoadingQueue with WorkQueue
kean Jan 5, 2025
126f6f9
Remove async Operation
kean Jan 5, 2025
82caa34
Remove obsolete TODO from ImagePrefetcher
kean Jan 5, 2025
1863cbd
Update some of the priority tests
kean Jan 14, 2025
603df05
Update DataCacheTests
kean Mar 30, 2025
a1b4fef
Update ResumableDataTests
kean Mar 30, 2025
2df8dac
Update LinkedListTests
kean Mar 30, 2025
cb6544d
Remove DeprecationTests
kean Mar 30, 2025
855b361
Update Sources to synchronized folders
kean Mar 30, 2025
f164752
Move Mocks to a synchronized folder
kean Mar 30, 2025
0929603
Move Extensions to Helpers
kean Mar 30, 2025
a22501b
Add Resources as a synchronized folder
kean Mar 30, 2025
3a411eb
Add other tests as synchronized folders
kean Mar 30, 2025
f026ead
Update Host
kean Mar 30, 2025
fbf8a87
Add Documentation as a synchronized folder
kean Mar 30, 2025
3421286
Async/Await tests are now standard
kean Mar 30, 2025
f1f2612
Update ImagePipelineTests
kean Mar 30, 2025
4f9dd09
Update minimum required versions
kean Mar 30, 2025
6e99e98
Require Swift 6
kean Mar 30, 2025
0d2f56f
Remove redundant #available checks
kean Mar 30, 2025
b4b4505
Update AsyncExpectation to support storing values
kean Mar 30, 2025
e51ff7c
Update WorkQueue.Item naming
kean Mar 30, 2025
c936eb1
Implement ImagePipelineTests.updatePriority
kean Mar 30, 2025
71c229c
Fix defaultPrioritySetToLow
kean Mar 31, 2025
e118453
Update ImagePipelineCacheTests
kean Mar 31, 2025
6d4fa16
Update imageDecodingQueue to be a WorkQueue
kean Mar 31, 2025
82c21c4
Update ImageProcessingQueue to use WorkQueue
kean Mar 31, 2025
6c2ce5f
Remove remaining OperationQueue usagse
kean Mar 31, 2025
0a86fdc
Update tests
kean Mar 31, 2025
d353726
Add dataLoadingOperationCancelled
kean Mar 31, 2025
fbeaba9
Add decodingOperationCancelled
kean Mar 31, 2025
1a233aa
Add decodingOperationCancelled
kean Mar 31, 2025
890862e
Add processingOperationCancelled
kean Mar 31, 2025
71fd921
Remove redundant @available
kean Mar 31, 2025
aa02047
Add DecompressionTests
kean Mar 31, 2025
0fd56ad
Add CacheKey tests
kean Mar 31, 2025
07e1fe1
Add pipeline invalidation tests
kean Mar 31, 2025
8b64acc
Add Error Handling tests
kean Mar 31, 2025
45b6521
Add remaining ImagePipelineTests
kean Mar 31, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ request.processors = [.resize(width: 320)]
- ``init(url:processors:priority:options:userInfo:)``
- ``init(urlRequest:processors:priority:options:userInfo:)``
- ``init(id:data:processors:priority:options:userInfo:)``
- ``init(id:dataPublisher:processors:priority:options:userInfo:)``
- ``init(stringLiteral:)``

### Options
Expand Down
64 changes: 28 additions & 36 deletions Nuke.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

30 changes: 3 additions & 27 deletions Sources/Nuke/Caching/DataCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,6 @@ public final class DataCache: DataCaching, @unchecked Sendable {
/// The time interval between cache sweeps. The default value is 1 hour.
public var sweepInterval: TimeInterval = 3600

// Deprecated in Nuke 12.2
@available(*, deprecated, message: "It's not recommended to use compression with the popular image formats that already compress the data")
public var isCompressionEnabled: Bool {
get { _isCompressionEnabled }
set { _isCompressionEnabled = newValue }
}
var _isCompressionEnabled = false

// Staging

private let lock = NSLock()
Expand Down Expand Up @@ -143,7 +135,7 @@ public final class DataCache: DataCaching, @unchecked Sendable {
guard let url = url(for: key) else {
return nil
}
return try? decompressed(Data(contentsOf: url))
return try? Data(contentsOf: url)
}

/// Returns `true` if the cache contains the data for the given key.
Expand Down Expand Up @@ -322,33 +314,17 @@ public final class DataCache: DataCaching, @unchecked Sendable {
switch change.type {
case let .add(data):
do {
try compressed(data).write(to: url)
try data.write(to: url)
} catch let error as NSError {
guard error.code == CocoaError.fileNoSuchFile.rawValue && error.domain == CocoaError.errorDomain else { return }
try? FileManager.default.createDirectory(at: self.path, withIntermediateDirectories: true, attributes: nil)
try? compressed(data).write(to: url) // re-create a directory and try again
try? data.write(to: url) // re-create a directory and try again
}
case .remove:
try? FileManager.default.removeItem(at: url)
}
}

// MARK: Compression

private func compressed(_ data: Data) throws -> Data {
guard _isCompressionEnabled else {
return data
}
return try (data as NSData).compressed(using: .lzfse) as Data
}

private func decompressed(_ data: Data) throws -> Data {
guard _isCompressionEnabled else {
return data
}
return try (data as NSData).decompressed(using: .lzfse) as Data
}

// MARK: Sweep

/// Synchronously performs a cache sweep and removes the least recently items
Expand Down
2 changes: 1 addition & 1 deletion Sources/Nuke/Decoding/ImageDecoderRegistry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public final class ImageDecoderRegistry: @unchecked Sendable {
}

/// Image decoding context used when selecting which decoder to use.
public struct ImageDecodingContext: @unchecked Sendable {
public struct ImageDecodingContext: Sendable {
public var request: ImageRequest
public var data: Data
/// Returns `true` if the download was completed.
Expand Down
2 changes: 1 addition & 1 deletion Sources/Nuke/Encoding/ImageEncoders+ImageIO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extension ImageEncoders {
self.compressionRatio = compressionRatio
}

private static let availability = Atomic<[AssetType: Bool]>(value: [:])
private static let availability = Mutex<[AssetType: Bool]>([:])

/// Returns `true` if the encoding is available for the given format on
/// the current hardware. Some of the most recent formats might not be
Expand Down
2 changes: 1 addition & 1 deletion Sources/Nuke/Encoding/ImageEncoding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ extension ImageEncoding {
}

/// Image encoding context used when selecting which encoder to use.
public struct ImageEncodingContext: @unchecked Sendable {
public struct ImageEncodingContext: Sendable {
public let request: ImageRequest
public let image: PlatformImage
public let urlResponse: URLResponse?
Expand Down
2 changes: 1 addition & 1 deletion Sources/Nuke/ImageContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public typealias PlatformImage = NSImage
#endif

/// An image container with an image and associated metadata.
public struct ImageContainer: @unchecked Sendable {
public struct ImageContainer: Sendable {
#if os(macOS)
/// A fetched image.
public var image: NSImage {
Expand Down
60 changes: 8 additions & 52 deletions Sources/Nuke/ImageRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public struct ImageRequest: CustomStringConvertible, Sendable, ExpressibleByStri
switch ref.resource {
case .url(let url): return url.map { URLRequest(url: $0) } // create lazily
case .urlRequest(let urlRequest): return urlRequest
case .publisher: return nil
case .closure: return nil
}
}

Expand All @@ -80,7 +80,7 @@ public struct ImageRequest: CustomStringConvertible, Sendable, ExpressibleByStri
switch ref.resource {
case .url(let url): return url
case .urlRequest(let request): return request.url
case .publisher: return nil
case .closure: return nil
}
}

Expand Down Expand Up @@ -202,51 +202,7 @@ public struct ImageRequest: CustomStringConvertible, Sendable, ExpressibleByStri
// pipeline by using a custom DataLoader and passing an async function in
// the request userInfo. g
self.ref = Container(
resource: .publisher(DataPublisher(id: id, data)),
processors: processors,
priority: priority,
options: options,
userInfo: userInfo
)
}

/// Initializes a request with the given data publisher.
///
/// For example, here is how you can use it with the Photos framework (the
/// `imageDataPublisher` API is a custom convenience extension not included
/// in the framework).
///
/// ```swift
/// let request = ImageRequest(
/// id: asset.localIdentifier,
/// dataPublisher: PHAssetManager.imageDataPublisher(for: asset)
/// )
/// ```
///
/// - important: If you are using a pipeline with a custom configuration that
/// enables aggressive disk cache, fetched data will be stored in this cache.
/// You can use ``Options-swift.struct/disableDiskCache`` to disable it.
///
/// - parameters:
/// - id: Uniquely identifies the fetched image.
/// - data: A data publisher to be used for fetching image data.
/// - processors: Processors to be apply to the image. See <doc:image-processing> to learn more.
/// - priority: The priority of the request, ``Priority-swift.enum/normal`` by default.
/// - options: Image loading options.
/// - userInfo: Custom info passed alongside the request.
public init<P>(
id: String,
dataPublisher: P,
processors: [any ImageProcessing] = [],
priority: Priority = .normal,
options: Options = [],
userInfo: [UserInfoKey: Any]? = nil
) where P: Publisher, P.Output == Data {
// It could technically be implemented without any special change to the
// pipeline by using a custom DataLoader and passing a publisher in the
// request userInfo.
self.ref = Container(
resource: .publisher(DataPublisher(id: id, dataPublisher)),
resource: .closure(data, id: id),
processors: processors,
priority: priority,
options: options,
Expand Down Expand Up @@ -470,8 +426,8 @@ public struct ImageRequest: CustomStringConvertible, Sendable, ExpressibleByStri
(ref.userInfo?[.scaleKey] as? NSNumber)?.floatValue
}

var publisher: DataPublisher? {
if case .publisher(let publisher) = ref.resource { return publisher }
var closure: (@Sendable () async throws -> Data)? {
if case .closure(let closure, _) = ref.resource { return closure }
return nil
}
}
Expand Down Expand Up @@ -519,21 +475,21 @@ extension ImageRequest {
enum Resource: CustomStringConvertible {
case url(URL?)
case urlRequest(URLRequest)
case publisher(DataPublisher)
case closure(@Sendable () async throws -> Data, id: String)

var description: String {
switch self {
case .url(let url): return "\(url?.absoluteString ?? "nil")"
case .urlRequest(let urlRequest): return "\(urlRequest)"
case .publisher(let data): return "\(data)"
case .closure(_, let id): return id
}
}

var imageId: String? {
switch self {
case .url(let url): return url?.absoluteString
case .urlRequest(let urlRequest): return urlRequest.url?.absoluteString
case .publisher(let publisher): return publisher.id
case .closure(_, let id): return id
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Nuke/ImageResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import AppKit
#endif

/// An image response that contains a fetched image and some metadata.
public struct ImageResponse: @unchecked Sendable {
public struct ImageResponse: Sendable {
/// An image container with an image and associated metadata.
public var container: ImageContainer

Expand Down
Loading
Loading