Xamarin.Nuke: a Xamarin binding for the iOS image caching library
![]() |
https://github.com/roubachof/NukeProxy |
Today's guest: The one and only Cheese Baron!
I know the cheeeese since my MVVMCross days when we were binding C# code on native views like aristocrats. For me he is one of the pillar of Xamarin open source community. So I was super happy when he reached out to me on Twitter about the nuke proxy subject.
You see, Xamarin.Forms iOS platform projects were super jealous of the outstanding work done by Jonathan Peppers with GlideX on Android:
https://devblogs.microsoft.com/xamarin/glidex-fast-images-android/
So I created the iOS version of this amazing Xamarin.Forms image handler:
https://github.com/roubachof/Xamarin.Forms.Nuke
This library is built on top of a binding library of Nuke. First I didn't put the binding project on Github, but some users reached out about it, so I gladly exposed it, but with a little doc and without any CI, or nuget package...
This was the state the repo was in when I received a ping on Twitter...
And now I leave the keyboard to your Baron.
The story
In search of a fast image loading library I stumbled over Jean-Marie's Xamarin.Nuke.Forms library which looked very promising.
However, I don't use Xamarin.Forms for my projects, so I needed just the Nuke parts, without the extra forms stuff. Jean-Marie, hadn't
published any of those on NuGet. However, he did publish the code he generated the Nuke bindings from. Shortly after this discovery
I reached out to ask if I could help making a package out of it.
First, one short step back. What is Nuke? It is a image loading system. A pretty fast and fairly popular one. Nuke works on iOS, WatchOS, macOS and tvOS.
It is written in Swift and all of it is Open Source on GitHub.
The part about being written in Swift is what makes Nuke a bit tricky to create bindings for. The way this works with Xamarin Binding libraries is roughly like this:
- Build the
swiftproject - Prepare metadata for
XamarinBindings - Build binding library with native library + metadata
- Enjoy
The only way to get the metadata to pick up the classes and methods in the swift project is to annotate your swift code with @objc to generate headers the metadata understands.
In a project like Nuke this is kind of a big task to do.
What then?!
Instead you can take the approach of making a small proxy library that consumes a Swift project and exposes the important surface of that project. This is the approach taken with
the bindings for Xamarin.Nuke. Hopefully sometime in the future we will get support for creating bindings for Swift projects without having to proxy it like this.
So looking at the NukeProxy project we expose the following surface:
-
ImagePipeline- load images various ways and cache themLoadImage- load image from URL into aUIImageViewand optionally supply placeholders for fail scenariosLoadData- load image from URL intoNSDatato be able to load it into for example a Skia Bitmap
-
ImageCacheRemoveAll- removes all cache entries
-
DataLoaderRemoveAllCachedResponses- removes all cached HTTP requests
-
Prefetcher- load images optimistically into cache for later useStartPrefetching- provide a collection of URLs to prefetchStopPrefetchingPauseUnPause
This is all exported by annotating a fairly short Swift class with the @objc annotation to surface headers for Objective-C code to consume.
To easily upgrade the version of the Nuke library to be bound, a fairly easy to use Pipeline has been set up using GitHub Actions. How we do it is as follows:
- Grab defined version of
NukefromCarthage - Build Nuke xcframework
- Build fat library of
NukeProxyforXamarinBinding to consume - Run Objective Sharpie to generate metadata
- Build
Xamarin.iOSbinding library with fat library +Nuke.framework - Generate NuGet package
To dial in this process I ended up trying some different things that didn't work.
- Instead of a Fat library for the
XamarinBinding I tried with a xcarchive, this doesn't seem to work - Instead of getting
NukefromCarthage, I tried usingSwift Package Managerand importing Nuke that way, this doesn't work as it doesn't produceNuke.frameworkin the output
In the end, just use fat libraries and you will have a much better time.
Grab the latest version of Xamarin.Nuke and give it a spin!
- nuke: https://github.com/kean/Nuke
- nukeproxy: https://github.com/roubachof/NukeProxy/blob/master/NukeProxy/NukeProxy.swift
- nuget: https://www.nuget.org/packages/Xamarin.Nuke/
The Sharpnado Silly Questions
The Sharpnado Silly Questions will now enter the private sphere of the contributor.
What are your top 3 best album/songs of all time?
Hard to say, this may change if you ask me some other time, but if I absolutely have to pick something like this:
- Iron Maiden - Seventh Son of a Seventh Son
- Opeth - Ghost Reveries
- Gojira - L'Enfant Sauvage
What are your top 3 best movies of all time?
- Pulp Fiction
- The Lord of the Rings - Fellowship of the Ring
- The Godfather
What is currently your favorite youtube video?
https://www.youtube.com/watch?v=YdFoO4DGXHw
Are you more a city, mountain, sea, or country person?
Woods or country.
What do you enjoy in life apart from coding?
Biking, walking and nerding out in different stuff.
What is your quest?
So far it has been to help people through my code in various ways
What is your favorite color?
Something around #3c26a0
