Kingfisher

repository·master·Indexed 12 days ago

https://github.com/onevcat/kingfisher

A pure-Swift library for downloading and caching images from the web. It supports UIKit, AppKit, and SwiftUI, featuring multi-layer hybrid caching, image processing, and prefetching. Version 8.0.0 provides a fluent API via the .kf extension and KF builder, including components like ImageDownloader, ImageCache, and KFImage for SwiftUI.

Tokens
29.8K
Snippets
85
Records
139
Agent score
98%

What's inside Kingfisher

  1. Getting Started with Kingfisher

    master

    Kingfisher is a library designed to facilitate the downloading and caching of remote images with minimal effort. It provides high-level abstractions for fetching, displaying, and manipulating images in both UIKit and SwiftUI environments.

    Core capabilities include:

    • Loading and Displaying Images: Effortlessly fetch and display images from remote URLs using view extensions.
    • Image Processing: Manipulate and transform images using the ImageProcessor functionality.
    • Cache Management: Inspect and manage the image cache status and lifecycle.

    For platform-specific implementation details, follow the UIKit or SwiftUI tutorials. If you are using AppKit, you can use the UIKit tutorials as a reference, as most concepts and APIs are shared across platforms.

  2. Overview of Kingfisher

    master

    Kingfisher is a lightweight, pure-Swift library designed for downloading and caching images from the web. It is framework-agnostic, supporting integration with UIKit, AppKit, and SwiftUI.

    Key capabilities include:

    • Downloading: Fetching images from remote URLs and displaying them in image views or buttons.
    • Caching: Storing images in both memory and disk to ensure immediate display on subsequent loads without re-downloading.
    • Processing: Applying pre-defined or custom image processors to downloaded images.
  3. Understand Kingfisher's file organization

    master

    Kingfisher is organized into several functional modules. Understanding this structure helps you locate specific components for your integration:

    • General: Core managers (KingfisherManager), the builder pattern API (KF), and core protocols.
    • Networking: Handles downloading, prefetching (ImagePrefetcher), and retry logic (RetryStrategy).
    • Cache: Multi-layer system including ImageCache, MemoryStorage, and DiskStorage.
    • Image: Processing protocols (ImageProcessor), built-in filters, and UI transitions.
    • Extensions: UIKit/AppKit integrations like ImageView+Kingfisher and UIButton+Kingfisher.
    • SwiftUI: SwiftUI-specific components like KFImage and KFAnimatedImage.
    • Utility/Views: Helper utilities and custom UI components.
  4. Overview of Kingfisher test infrastructure

    master

    Kingfisher's test suite is built on the following components:

    • Framework: XCTest
    • Network Mocking: Nocilla (used for HTTP request stubbing)
    • Test Helpers: KingfisherTestHelper.swift provides pre-encoded image data (PNG, JPEG, GIF, HEIC, MOV), cache cleanup utilities (cleanDefaultCache, clearCaches), and image comparison with tolerance (renderEqual).
    • Stub Utilities: StubHelpers.swift provides stub() for creating HTTP response stubs and delayedStub() for timing-related tests.
  5. Overview of Kingfisher Architecture

    master

    Kingfisher is a modular Swift library for image loading and caching. It uses a protocol-oriented design and a namespace pattern (.kf) to provide a consistent API across UIKit, AppKit, and SwiftUI.

    Key architectural components include:

    • KingfisherManager: The central coordinator for the image loading workflow.
    • ImageDownloader: Handles network tasks and HTTP image downloading.
    • ImageCache: A dual-layer caching system consisting of MemoryStorage (LRU in-memory cache) and DiskStorage (persistent disk storage).
    • ImageProcessor: Manages the transformation pipeline (filters, resizing, etc.).
    • KF.swift: The main entry point providing a builder pattern API for image tasks.
  6. What is an ImageDataProvider and how does it work?

    master

    An ImageDataProvider is a protocol that allows Kingfisher to load images from local data sources instead of network URLs. By using a provider, you can leverage Kingfisher's full suite of features—such as image processing, caching, and cache serializers—on data that is already on the device.

    To use an ImageDataProvider, you pass it to the setImage(with:options:) method on a KFImage instance (e.g., imageView.kf.setImage(with: provider)).

  7. Why `cancelDownloadTask()` might not prevent memory spikes

    master

    The cancelDownloadTask() method calls DownloadTask.cancel(), which specifically targets network downloads (SessionDataTask).

    If an image is being retrieved from the disk cache, KingfisherManager.retrieveImage returns nil for the download task, meaning there is no active DownloadTask to cancel. Consequently, once the disk retrieval process has started on the ioQueue, the chain of disk reading, deserialization, and memory promotion cannot be interrupted by standard download cancellation.

  8. How the Options pattern works

    master

    Kingfisher uses an Options Pattern to handle flexible customization of image loading tasks.

    1. KingfisherOptionsInfoItem: An enum representing individual configuration items (e.g., .targetCache, .downloader, .transition, .forceRefresh).
    2. KingfisherParsedOptionsInfo: A struct that holds the actual values for these options, used internally by the engine to execute the request.

    When calling methods like setImage(with:options:), you pass an array of these enum cases.

    // Example of passing options
    imageView.kf.setImage(
        with: url,
        options: [.transition(.fade(0.2)), .cacheMemoryOnly]
    )
  9. How the `.kf` namespace works

    master

    Kingfisher uses a Namespace Wrapper Pattern to provide a clean, scoped API on compatible types. Instead of polluting the global namespace of objects like UIImageView or NSImageView, Kingfisher adds a .kf property via the KingfisherCompatible protocol. This property returns a KingfisherWrapper which acts as a gateway to all Kingfisher-specific extensions and methods.

    To make a type compatible with Kingfisher, it must conform to KingfisherCompatible.

    // Implementation detail of the pattern
    public protocol KingfisherCompatible: AnyObject { }
    
    extension KingfisherCompatible {
        public var kf: KingfisherWrapper<Self> {
            get { return KingfisherWrapper(self) }
            set { }
        }
    }
    
    // Usage: conforming a type
    extension UIImageView: KingfisherCompatible { }
    
    // Usage: accessing the namespace
    imageView.kf.setImage(with: url)
  10. Caching System Layers

    master

    Kingfisher uses a dual-layer caching strategy to balance speed and persistence:

    • Memory Cache (MemoryStorage): An in-memory LRU (Least Recently Used) cache that includes automatic cleanup.
    • Disk Cache (DiskStorage): Persistent storage with expiration policies.
    • ImageCache: The coordinator that manages both memory and disk layers.
    • CacheSerializer: Handles image serialization for disk persistence (e.g., FormatIndicatedCacheSerializer for format-aware serialization).
  11. Verify the completion handler contract for cancelled tasks

    master

    Even when a task is skipped due to a stale taskIdentifier, Kingfisher guarantees that every setImage call produces exactly one completion callback.

    If a task is skipped:

    1. The cache retrieval returns a failure (e.g., .imageNotExisting).
    2. The view extension detects that the issuedIdentifier does not match the current taskIdentifier.
    3. The completion handler is called with a .notCurrentSourceTask error.

    This ensures that your application logic always receives a response for every request, preventing hanging callbacks.

  12. Testing asynchronous requests with Nocilla

    master
    When testing asynchronous requests, remember that the request is executed on a different thread than the test execution. Ensure your test framework (like XCTest, Quick, or Nimble) is configured to wait for the request to complete. Using tearDown() or afterEach() too early may cause the request to never finish.