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
swift
project - Prepare metadata for
Xamarin
Bindings - 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 aUIImageView
and optionally supply placeholders for fail scenariosLoadData
- load image from URL intoNSData
to be able to load it into for example a Skia Bitmap
-
ImageCache
RemoveAll
- removes all cache entries
-
DataLoader
RemoveAllCachedResponses
- removes all cached HTTP requests
-
Prefetcher
- load images optimistically into cache for later useStartPrefetching
- provide a collection of URLs to prefetchStopPrefetching
Pause
UnPause
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
Nuke
fromCarthage
- Build Nuke xcframework
- Build fat library of
NukeProxy
forXamarin
Binding to consume - Run Objective Sharpie to generate metadata
- Build
Xamarin.iOS
binding 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
Xamarin
Binding I tried with a xcarchive, this doesn't seem to work - Instead of getting
Nuke
fromCarthage
, I tried usingSwift Package Manager
and importing Nuke that way, this doesn't work as it doesn't produceNuke.framework
in 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