/Nuke

A powerful image loading and caching framework

Primary LanguageSwiftMIT LicenseMIT

A powerful image loading and caching framework which allows for hassle-free image loading in your app.

Features

Quick Start

Upgrading from the previous version? Use a migration guide.

Usage

Loading Images into Targets

You can load an image into an image view with a single line of code. Nuke will automatically load image data, decompress it in the background, store the image in the memory cache, and finally display it.

Nuke.loadImage(with: url, into: imageView)

Reusing Targets

Nuke.loadImage(with:into:) method cancels previous outstanding request associated with the target. Nuke holds a weak reference to a target, when the target is deallocated the associated request gets cancelled automatically.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    ...
    cell.imageView.image = nil
    Nuke.loadImage(with: url, into: cell.imageView)
    ...
}

Supporting Custom Targets

A target can be any class that implements a Target protocol:

extension UIButton: Nuke.Target {
    func handle(response: Result<Image>, isFromMemoryCache: Bool) {
        setImage(response.value, for: .normal)
    }
}

Providing Custom Handlers

Nuke also has a flexible loadImage(with:into:handler:) method which lets you handle the response by passing a closure:

indicator.startAnimating()
Nuke.loadImage(with: request, into: view) { [weak view] response, _ in
    view?.image = response.value
    indicator.stopAnimating()
}

The target in this method is declared as AnyObject with which the requests get associated. This enables a number of use cases. For example, with a couple lines of code you can show a low-res image and swap to a higher-res one when loaded.

Customizing Requests

Each request is represented by Request struct. A request can be created either with a URL or with a URLRequest.

var request = Request(url: url)
// var request = Request(urlRequest: URLRequest(url: url))

// A request has a number of options that you can change:
request.memoryCacheOptions.writeAllowed = false

Nuke.loadImage(with: request, into: imageView)

Processing Images

Nuke provides an infrastructure for processing images and caching them. You can specify custom image processors using Processing protocol which consists of a single method process(image: Image) -> Image?:

struct GaussianBlur: Processing {
    var radius = 8

    func process(image: UIImage) -> UIImage? {
        return image.applyFilter(CIFilter(name: "CIGaussianBlur", withInputParameters: ["inputRadius" : self.radius]))
    }

    // `Processing` protocol requires `Equatable` to identify cached images.
    func ==(lhs: GaussianBlur, rhs: GaussianBlur) -> Bool {
        return lhs.radius == rhs.radius // If the processor has no parameters, simply return true
    }
}

// Usage:
let request = Request(url: url).processed(with: GaussianBlur())
Nuke.loadImage(with: request, into: imageView)

See Core Image Integration Guide for more info about using Core Image with Nuke

Using Toucan Plugin

Check out Toucan Plugin for some useful image transformations. Toucan is a library that provides a clean API for processing images, including resizing, elliptical and rounded rect masking, and more:

let request = Nuke.Request(url: url).processed(key: "Avatar") { 
    return $0.resize(CGSize(width: 500, height: 500), fitMode: .crop)
             .maskWithEllipse()
}

Loading Images w/o Targets

You can also use Manager to load images directly without providing a target.

Manager.shared.loadImage(with: url) {
    print("image \($0.value)")
}

If you'd like to be able to cancel the requests use a cancellation token:

let cts = CancellationTokenSource()
Manager.shared.loadImage(with: url, token: cts.token) {
    print("image \($0.value)")
}
cts.cancel()

Using Memory Cache

You can get a directly access to the default memory cache used by Nuke:

Cache.shared.costLimit = 1024 * 1024 * 100 // 100 MB
Cache.shared.countLimit = 100

let request = Request(url: url)
Cache.shared[request] = image
let image = Cache.shared[request]

Preheating Images

Preheating (prefetching) means loading images ahead of time in anticipation of its use. Nuke provides a Preheater class that does just that:

let preheater = Preheater(manager: Manager.shared)

// User enters the screen:
let requests = [Request(url: url1), Request(url: url2), ...]
preheater.startPreheating(for: requests)

// User leaves the screen:
preheater.stopPreheating(for: requests)

You can use Nuke in combination with Preheat library which automates preheating of content in UICollectionView and UITableView. With iOS 10.0 you might want to use new prefetching APIs provided by iOS.

See Performance Guide to see what else you can do to improve performance

Plugins

Allows you to replace networking layer with Alamofire. Combine the power of both frameworks!

Gifu plugin allows you to load and display animated GIFs.

Toucan plugin provides a simple API for processing images. It supports resizing, cropping, rounded rect masking and more.

FLAnimatedImage plugin allows you to load and display animated GIFs with smooth scrolling performance and low memory footprint.

Design

Nuke is designed to support dependency injection. It provides a set of protocols - each with a single responsibility - which manage loading, decoding, processing, and caching images. You can easily create and inject your own implementations of those protocols:

Protocol Description
Loading Loads images
DataLoading Downloads data
DataDecoding Converts data into image objects
Processing Image transformations
Caching Stores images into memory cache

Data Loading and Caching

Nuke has a basic built-in DataLoader class that implements DataLoading protocol. It uses Foundation.URLSession which is a part of the Foundation's URL Loading System. Another part of it is Foundation.URLCache which provides a composite in-memory and on-disk cache for data. By default it is initialized with a memory capacity of 0 MB (Nuke only stores decompressed images in memory) and a disk capacity of 150 MB.

See Image Caching Guide to learn more about URLCache, HTTP caching, and more

If you'd like to use a third-party caching library check out Third Party Libraries: Using Other Caching Libraries

Most developers either have their own networking layer, or use some third-party framework. Nuke supports both of these workflows. You can integrate a custom networking layer by implementing DataLoading protocol.

See Alamofire Plugin that implements DataLoading protocol using Alamofire framework

If you'd like to use your own network layer see Third Party Libraries: Using Other Networking Libraries

Memory Cache

Nuke provides a fast in-memory Cache that implements Caching protocol. It stores processed images ready to be displayed. Cache uses LRU (least-recently used) replacement algorithm. By default it is initialized with a memory capacity of 20% of the available RAM. As a good citizen Cache automatically evicts images on memory warnings, and removes most of the images when application enters background.

Requirements

  • iOS 9.0 / watchOS 2.0 / macOS 10.11 / tvOS 9.0
  • Xcode 8
  • Swift 3

License

Nuke is available under the MIT license. See the LICENSE file for more info.