Monday, July 03, 2017

Troubleshooting Xamarin iPhoneSimulator errors from Visual Studio

I’m using the Xamarin Mac BuildAgent to compile my Xamarin.Forms app from Visual Studio and test it using the device simulator on my Mac. This solution was working really well for me until one day, it wasn’t. I could compile and deploy to the Simulator fine, but I was seeing errors at runtime that simply weren’t there on Android or UWP. To make matters worse, my colleagues weren’t seeing this problem when compiling and deploying to an actual device.

The problem started when we added Azure Mobile Services to our project. The errors we were seeing weren’t very helpful at all, either a TypeLoadException or NullReferenceException and they appear when trying to invoke calls that were part of the Mobile Services client. These errors are frustrating because the error detail in Visual Studio provides little guidance as to why these calls aren’t working, especially when the same calls were working before adding the reference.

The forums and usage for Azure Mobile Services recommends that you must invoke CurrentPlatform.Init() to ensure that some of the extended assemblies that are dynamically loaded at runtime are linked into the output during compilation. I’ve seen similar problems before in WPF where the compilation process would optimize away assemblies that contain only DataTemplates and Styles – effectively, if they don’t contain byte-code then the compiler will not list the reference as a dependency.

Unfortunately our team was already using CurrentPlatform.Init() in our code, and since the error was only specific to the iPhoneSimulator it suggested an issue with the Linking used for the Debug_iPhoneSimulator configuration. Although the Linker Behavior is set to Don’t link – which effectively takes all assemblies without attempting to optimize – we added the –linkskip arguments to both the main Azure Mobile Service assembly and its platform equivalent (Microsoft.WindowsAzure.Mobile.Ext).

image

This strangely seemed to resolve the issue, at least partially. We could get further along in our app initialization before the app would hang.

Inspecting the Logs

Often, the errors from Xamarin will recommend checking the logs. There are two logs to check:

  • Xamarin Logs. These logs are found through Visual Studio: Help –> Xamarin –> Open Logs. They show diagnostics for Xamarin within Visual Studio and are especially useful for understanding deployment errors such as connectivity with the Mac BuildAgent.
  • Device Logs. These logs can be found on the Mac. Simulator: Debug –> Open System Log. These logs contain the paydirt of what’s happening with the logs and provides insights into the inner exceptions that don’t bubble up into Visual Studio.

In my case, looking at the Simulator’s Device Log showed the critical missing piece of information. I was missing a reference to a reference. I was missing a reference to System.Net.Http!

Jul 2 13:35:15 Bryans-MacBook-Pro MyAppiOS[24157]: Could not find `System.Net.Http` referenced by assembly `Xamarin.Forms.Platform.iOS, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null`. 
Jul 2 13:35:15 Bryans-MacBook-Pro MyAppiOS[24157]: Could not find `System.Net.Http` referenced by assembly `Microsoft.WindowsAzure.Mobile, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35`. 
Jul 2 13:35:15 Bryans-MacBook-Pro MyAppiOS[24157]: Could not find `System.Net.Http` referenced by assembly `Xamarin.Auth, Version=1.3.0.0, Culture=neutral, PublicKeyToken=null`. 
Jul 2 13:35:15 Bryans-MacBook-Pro MyAppiOS[24157]: Could not find `System.Net.Http` referenced by assembly `Microsoft.WindowsAzure.Storage, Version=7.1.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35`.

The logs contain .NET StackTraces and Exception details, which provide excellent supporting information for errors that occur in the IDE. And now that the simulator actually works it’ll be used a great deal more often.