What is… Nuke?
This article gives a quick overview of Nuke, an open source Swift framework for loading, processing, caching, displaying, and preheating images. By Rui Peres.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Downloading and caching images efficiently has long been a challenge for iOS developers.
Objective-C has lots of popular libraries to aid in this task, such as SDWebImage
, AFNetworking
, DFImageManager
and more. It’s taken some time for comparable Swift libraries to show up, but one of the newest is Nuke!
Nuke is an open source Swift framework for loading, processing, caching, displaying, and preheating images. It is written by Alexander Grebenyuk, an experienced developer who also wrote DFImageManager
.
In this article, I’ll give you a quick overview of installing Nuke and how to use it, and then outline the situations where you might find it useful in your apps. Let’s get started!
Getting Started
Installing Nuke is easy – it supports both CocoaPods and Carthage.
CocoaPods
If you use CocoaPods, simply add the following lines to your
pod "Nuke"
pod "Nuke-Alamofire-Plugin" # optional
pod "Nuke-AnimatedImage-Plugin" # optional
Carthage
If you use Carthage, simply add the following lines to your Cartfile:
github "kean/Nuke"
github "kean/Nuke-Alamofire-Plugin" # optional
Currently, there is no Carthage support for the Nuke-AnimatedImage-Plugin.
What Nuke Does
Nuke helps you do 6 main things:
- Download Images
- Resize Images
- Cache Images
- Process Images
- Deserialize and Decode Images
- Preheat Images
Let’s look at each in turn.
1) Download Images
The primary goal of Nuke is to make downloading and using images in your app quick, easy, and efficient.
For example, the following snippet fetches an image for you:
Nuke.taskWithURL(url) { response in
switch response {
case let .Success(image, responseInfo):
//do something with your image
case let .Failure(error):
//handle the error case
}
}.resume()
Here, you simply pass in an instance of NSURL
then call resume
. Nuke will download your image in the background and call your response closure when it’s done.
response
is an enum
that describes the task’s outcome either as a success or a failure. responseInfo
provides useful information to the caller, such as fastResponse
, which tells you if the fetched image is from the network or the cache.
Although ImageTask
doesn’t descend from NSURLSessionTask
, ImageTask
offers similar API methods such as resume
, suspend
, and cancel
for managing your network calls.
NSURLSessionTask
. In Nuke’s case, you’re using ImageTask
instead of NSURLSessionTask
.
Although ImageTask
doesn’t descend from NSURLSessionTask
, ImageTask
offers similar API methods such as resume
, suspend
, and cancel
for managing your network calls.
2) Resize Images
So far, this is no different than what you can do with NSURLSession
or other networking libraries. But you can also pass some image-specific parameters to your download task, by passing an ImageRequest
instead of an NSURL
, as in the example below:
var imageRequest = ImageRequest(URL: imageURL)
request.targetSize = CGSize(width: 250, height: 250)
request.contentMode = .AspectFit
Nuke.taskWithRequest(request) { response in
// Handle the response
switch response {
case let .Success(image, responseInfo):
let image = image
case let .Failure(error):
let error = error
}
}.resume()
This lets you specify elements such as the target size to resize the image to, and how to do so via contentMode
(AspectFill
or AspectFit
). Nuke will download and resize the image for you in the background.
Couldn’t you just hand UIImageView
a large image and let the resizing happen behind the scenes? You could do this, and UIImageView
would internally resize the image depending on the the image view’s contentMode
property. However, it’s better to resize the image yourself before handing it off to UIImageView
so you can keep memory usage at a minimum. That’s where Nuke comes in handy.
Couldn’t you just hand UIImageView
a large image and let the resizing happen behind the scenes? You could do this, and UIImageView
would internally resize the image depending on the the image view’s contentMode
property. However, it’s better to resize the image yourself before handing it off to UIImageView
so you can keep memory usage at a minimum. That’s where Nuke comes in handy.
3) Cache Images
If you use Nuke, the images you download will be cached automatically. To understand how this works, check out the following quote from Nuke’s caching mechanism guide:
Rather than reinventing caching, Nuke relies on two built-in caching mechanisms offered by Apple:
-
NSURLSession
‘s caching mechanism viaNSURLCache
NSCache
NSURLSession
provides both disk and in-memory caching; it’s controlled primarily by the HTTP headers sent back in response to your request. NSCache
is an in-memory cache that sits on top of the URL loading framework’s caching mechanism to make things even faster.
The added benefit of using NSURLCache
is that it’s completely transparent to the user. After requesting an image, you can verify its existence in the cache by checking the default NSURLCache
singleton like so:
let cachedResponse = NSURLCache.sharedURLCache().cachedResponseForRequest(imageRequest)
4) Process Images
Besides downloading and caching the image, ImageRequest
also allows you define custom filters to apply to the fetched image. Yes, you could technically do this by yourself, but it’s still a nice touch.
The code below shows how easy it can be to add a blur effect to your retrieved image:
let blurringImageFilter : ImageProcessing = MyFilters.blurringFilter()
var imageRequest = ImageRequest(URL: imageURL)
imageRequest.processor = blurringImageFilter
Nuke.taskWithRequest(request) { response in
switch response {
// Handle the response
case let .Success(image, responseInfo):
let image = image
case let .Failure(error):
let error = error
}
}.resume()
The key element in the code above is Nuke’s ImageProcessing
protocol. It defines several methods you must comply with; the most important one is this:
func processImage(image: UIImage) -> UIImage?
You pass this method an instance of UIImage
and it returns an UIImage
optional. If the filter operation succeeds, you get a new image with the filter already applied. If Nuke can’t apply the filter for whatever reason, it returns nil
. It’s quite straightforward!