github kean/Nuke 13.1.0
Nuke 13.1.0

5 hours ago

What's Changed

  • Fix GaussianBlur crash on grayscale images by @Delarkz in #880
  • Fix cache initialization for mergeable libraries by @ZHUOLIN0928 in #881
  • Add asynchronous image decoding support by @thliu21 in #879
  • Fix a leak where requests that finish synchronously – memory cache hits, disk cache hits for data(for:), local resources, .returnCacheDataDontLoad misses, and malformed URLs – were never removed from the pipeline, retaining their responses for its lifetime
  • Fix ImageTask.Event.started being delivered to ImagePipelineDelegate after .finished for requests that finish synchronously
  • Fix a data race in ImageDecoderRegistry where decoder(for:) iterated the registered decoders without holding the lock. The registry is now backed by Mutex and is Sendable instead of @unchecked Sendable; the closures are called outside of the lock
  • ImageDecoderRegistry.register(_:) now takes a @Sendable closure. The registry is shared between the pipelines and the closures are called on the decoding threads, so registrations capturing non-Sendable state now fail to compile instead of silently escaping the check
  • Add ImageDecoderRegistry.unregister(_:). register(_:) now returns a discardable ImageDecoderRegistry.RegistrationToken for removing an individual decoder instead of clearing the entire registry
  • Fix DataLoader calling completion twice when response validation fails, violating the DataLoading contract. The handler is now unregistered before the task is cancelled, so the URLError(.cancelled) from didCompleteWithError no longer follows the validation error
  • Fix a request cancelled while ImagePipelineDelegate/willLoadData(for:urlRequest:pipeline:) was suspended still running the download to completion, discarding the result and occupying a slot in dataLoadingQueue. The pipeline now re-checks for cancellation when the delegate returns
  • Fix resumable data being lost when a request ended before the server responded. The pipeline takes the data out of the storage before loading and now puts it back if nothing new was downloaded
  • Fix requests with ImageRequest/Options/skipDataLoadingQueue not cancelling the underlying Task, leaving an async willLoadData or a custom data fetch closure running after cancellation
  • Fix the async/await variant of FetchImage/load(_:) delivering a result after the load was cancelled or superseded. Task cancellation is cooperative, so an action that doesn't check for it runs to completion – its result is now discarded instead of overwriting the state of the newer load, flipping isLoading off mid-load, and calling onCompletion
  • Fix LazyImage with the LazyImage/DisappearBehavior/lowerPriority disappear behavior permanently lowering the priority of its requests after the view goes off-screen. The override wasn't reset when the view reappeared, so every subsequent load ran with .veryLow priority, ignoring LazyImage/priority(_:)
  • Fix LazyImageView stacking the views created by LazyImageView/makeImageView. A view was added for every displayed response – each progressive preview, the cached preview, and the final image – without removing the previous one, so the orphaned views survived cell reuse, covered the newer content, and retained their images
  • Fix ImagePrefetcher/stopPrefetching(with:) and ImagePrefetcher/stopPrefetching() doing nothing for the prefetches that were scheduled but haven't started yet. In the standard collection view pattern – startPrefetching immediately followed by stopPrefetching – the requests ran the entire download/decode/cache cycle anyway. It also affected the requests cancelled when the prefetcher is deallocated, and the priority updates
  • Fix ImageDecoders/Empty not marking the containers returned by decodePartiallyDownloadedData(_:) as previews. Downstream checks treated the truncated data as a final image, so it was stored in the memory cache regardless of ImagePipeline/Configuration/isStoringPreviewsInMemoryCache, encoded into the data cache with ImagePipeline/DataCachePolicy/storeEncodedImages, and delivered as a completed response on the subsequent cache hits
  • Fix ImageProcessors/CoreImageFilter sharing a single mutable CIFilter between concurrently processed images. CIFilter is not thread-safe – the processor sets the input image and then reads the output – so a processor created with ImageProcessors/CoreImageFilter/init(_:identifier:) could produce an image from another request's input and cache it under the wrong key. ImageProcessors/CoreImageFilter/apply(filter:to:) now applies a copy, leaving the original untouched
  • Fix the screen scale used by ImageProcessingOptions/Unit/points being read once and cached for the lifetime of the process. UITraitCollection.current is only populated in the contexts managed by UIKit and reports a 0 display scale everywhere else, so if the first points-based ImageRequest was created on a background thread, every subsequent resize computed a zero target size and failed with ImagePipeline/Error/processingFailed(processor:context:error:), and the point-based border widths and corner radii became 0. The scale is now re-evaluated on every access, falling back to the last known valid value
  • Fix progressive previews being permanently disabled when the first downloaded chunk isn't enough to tell that the image supports them. The decoder is created from the first chunk and configured with the preview policy computed for it, but ImagePipeline/PreviewPolicy/default(for:) returns ImagePipeline/PreviewPolicy/disabled until Image I/O can parse the frame header – which for progressive JPEGs with large EXIF/ICC preambles doesn't happen until well into the download, producing zero previews. The policy is now re-evaluated as more data arrives and the decoder is replaced if it changes. Re-evaluation stops as soon as the policy produces previews, requires the data to at least double, and has a hard cap, so the pipeline no longer parses the partially downloaded data on every chunk
  • Fix ImagePrefetcher/priority not reaching the prefetches that were scheduled but haven't started yet. The new priority was applied to the queue slot and the existing ImageTask instances, but the pending prefetches kept the priority frozen in their original requests, so they eventually did the actual work – data loading, decoding, processing – at the old priority
  • Fix a crash on macOS when an ImageProcessingOptions/Border is created with an NSColor outside an RGB colorspace – including .black, .white, the grays, and the catalog colors such as .labelColor. Unlike UIColor, NSColor doesn't convert on the fly and raises an NSInvalidArgumentException from getRed(_:green:blue:alpha:), so merely reading ImageProcessors/Circle/identifier or ImageProcessors/RoundedCorners/identifier – which happens on every request when a data cache is configured – terminated the process. The color is now converted to sRGB first

New Contributors

Full Changelog: 13.0.6...13.1.0

Don't miss a new Nuke release

NewReleases is sending notifications on new releases.