Exploring Swift generic functions with WallpapersKit
Today I’ve been updating BingWallpapers to use the last version of Swift and also include the latest changes of WallpapersKit, the framework that is shared across the Mac and iOS versions.
I’ve been developing WallpapersKit letting the code guide it’s own design and today I made some changes using generic functions.
In WallpapersKit there is an extension to the main core class that contains a function with the following signature:
fetchImageFromWallpaper(wallpaper: Wallpaper, downloadImage: (url: NSURL, success: (Image) -> (), fail: (NSError) -> ()) -> (), completion: (url: NSURL?, image: Image?, error: NSError?) -> ())
In the source it’s nicer with some typealias but here I want to be explicit. This function contains the logic to download the right image from the
wallpaper. It tries to download the image with the desired quality and if it fails it has some fallbacks. The nice part is the
downloadImage: (url: NSURL, success: (Image) -> (), fail: (NSError) -> ()) -> ()
This closure takes an URL and a success and failure closures. In this way WallpapersKit can contain the required logic to deal with the wallpapers, the different urls and qualities, but it doesn’t have to care on how to actually download the image. That has turn out to be really great because the Mac and iOS apps do different things when downloading the images.
On iOS I’m currently using the Haneke library to download and cache the images. For convenience I have defined a subspec, thanks to Cocoapods, that includes a version of the
fetchImageFromWallpaper function but with a default
downloadImage closure. This is the only place where the framework has the dependency. Having this in a subspec means that the iOS App can use this handy function in the main app and in the extension (Today widget).
The OS X app needs something different. There I don’t import the subspec, so it doesn’t have any dependency with the third party library to cache images. It has it’s own implementation of the
downloadImage function that downloads the data of the image and saves it directly to disk (in a Application Support subfolder).
It doesn’t need at all to create an
NSImage, it only has to download the
NSData. That’s because the OS X API to change the Desktop background only needs a disk path, so is less work that we have to do.
To accomplish that difference in the requirements I’ve modified the original function to make it generic. Now instead of talking about Image it talks about a generic type.