Use Nuke in the App

Use Nuke in the App

2018, Feb 10    

Swift is the major reason, I start to work on iOS/Mac app. Before I use electron and Xamarin Form

There are many Image Loading/Cache library on github, like SDWebImage (objc), Kingfisher (Swift).

And I found a new one, and some useful plugin.

Nuke https://github.com/kean/Nuke Alamofire https://github.com/kean/Nuke-Alamofire-Plugin Gifu https://github.com/kean/Nuke-Gifu-Plugin RxNuke https://github.com/kean/RxNuke

Create a Manager

class NukeManager {
    public static let shared: Nuke.Manager = {
        // Define decoding sequence
        let animatedImageDecode = AnimatedImageDecoder() // Use Gifu for 
        let dataDecoder = Nuke.DataDecoder()
        let webpDataDecoder = WebPDataDecoder()

        // Make a decoder which supports animated GIFs.
        let decoder = Nuke.DataDecoderComposition(decoders: [webpDataDecoder, animatedImageDecode, dataDecoder])
    
        // Updates `Cache` cost calculation block.
        let cache = Nuke.Cache().preparedForAnimatedImages()
        
        var options = Nuke.Loader.Options()
        // Disable processing of animated images.
        options.processor = { image, request in
            return image is AnimatedImage ? nil : request.processor
        }
        
        // Use the Nuke default configuration
        let sessionManager = Alamofire.SessionManager(configuration: Nuke.DataLoader.defaultConfiguration)
        
        // Use Alamofire Loader, with preconfigured Decoder
        let loader = Nuke.Loader(loader: NukeAlamofirePlugin.DataLoader(manager: sessionManager), decoder: decoder, options: options)
        
        return Manager(loader: loader, cache: cache)
    }()
}

Use the manager to loadImage

NukeManager.manager.loadImage(with: URL(), into: animatedImageView)

Some tweak to Nuke WebP Plugin

Add default constructor, if not WebP format return nil

public struct WebPDataDecoder: Nuke.DataDecoding {

    //https://github.com/kean/Nuke-Gifu-Plugin/blob/master/Source/AnimatedImage.swift#L64
    public init() {}
    
    public func decode(data: Data, response: URLResponse) -> Image? {
        if !data.isWebPFormat {
            return nil
        }
        return decodeWebPData(data)
    }

}

Check if Data is WebP

// MARK: - WebP Format Testing
extension Data {
    var isWebPFormat: Bool {
        if count < 12 {
            return false
        }
        
        let endIndex = index(startIndex, offsetBy: 12)
        let testData = subdata(in: startIndex..<endIndex)
        guard let testString = String(data: testData, encoding: .ascii) else {
            return false
        }
        
        if testString.hasPrefix("RIFF") && testString.hasSuffix("WEBP") {
            return true
        } else {
            return false
        }
    }
}