Crash in iOS Apps for iPhone 6 Plus Built with Xamarin Studio 5.5.4 – The @3x Problem

My client recently submitted an update to our app suite, developed with Xamarin to easily generate all kinds of derivates with different styling, and to be able to serve both iOS and Android.
The most recent update included optimizations for iOS8 and iPhone 6 and iPhone 6 Plus.

I’ve adjusted any necessary layouting rules and added the Default-667@2x.png and Default-736@3x.png files I was also referencing from code via

string imageName = Utilities.iOS.Device.IsIPhone5OrGreater ? 
                   "Default-"+ UIScreen.MainScreen.Bounds.Height +"h" 
                   : "Default";
UIImage image = UIImage.FromBundle(imageName);

and tested the app in the simulator on both iPhone 6 and 6 Plus. Everything worked like a charm. We didn’t have any actual iPhone 6 Plus to test on, so we submitted.

Today, we’ve become aware of 100% replicable crashes on this device.
The crashlog indicated it must be something caused by an exception, where the system kills the app:

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib        	0x35682dfc 0x3566e000 + 85500
1   libsystem_pthread.dylib       	0x35700d33 0x356fd000 + 15667
2   libsystem_c.dylib             	0x35622905 0x355d8000 + 305413
3   MyApp                       	0x0054d3b3 0xd1000 + 4703155

After connecting the debugger to an iPhone 6 Plus, I was able to figure out the issue – which is quite … well, let’s call it shocking.

Usually, when working with @2x, the only thing you need to provide in the image name string is the bit before the @2x.png and the system itself searches for that image with that name in the appropriate resolution. Obviously, you’d expect @3x to work accordingly.

Sadly, UIImage image = UIImage.FromBundle(imageName); returns null when provided with an image name that has @3x.png as an ending (e.g. Default-763@3x.png) and doesn’t exist as normal-res or @2x (e.g. Default-763@2x.png and/or Default-763.png).
I mean in this case, why should it?!?

I’ve noticed though, that I get a valid image when I pass Default-763@3x for my image name in UIImage.FromBundle(imageName). So I’ve added a few lines of code to make sure the problem doesn’t occur anymore and won’t pose any trouble once the issue is fixed:

string imageName = Utilities.iOS.Device.IsIPhone5OrGreater ? 
                   "Default-"+ UIScreen.MainScreen.Bounds.Height +"h" :
                   "Default";
UIImage image =  UIImage.FromBundle(imageName);
if (image == null && imageName.Contains("736")) {
    imageName = imageName + "@3x";
    image = UIImage.FromBundle (imageName);
}