Debugging a cross platform app presents some challenges. What happens when you debug something that builds to a couple of platforms?
Here’s a simplified description of the Xamarin framework and tips on how to resolve those platform specific exceptions.
Disclaimer: my viewpoint is Xamarin.Forms but the same applies to Xamarin.Android / Xamarin.iOS even without Forms involved.
What actually happens (simplified)
You got to be aware of the process that is Xamarin: code you write (in PCL if Xamarin.Forms) actually becomes the target language in the end: Java for Android, Swift/Objective-C for iOS – but still C# for Windows.
So when an exception occurs it does so on the target platform and got to bubble up all the way to your environment. I.E
- Android app = Java > Xamarin Android > Visual / Xamarin Studio
- iOS app = Swift / Objective-C > Xamarin iOS > Visual / Xamarin Studio
- Windows app = C# > Visual Studio
You saw it right – shortest path is Windows > Windows (shocking). What does this mean for your debugging then?
I’ll tackle the other two first since they are the real issue.
Catching Android / iOS Exceptions
If you’ve developed for literally anything else the exception is usually pretty straight forward: “there’s an error here on this line in this function because you didn’t check twice before running” (also K.I.S.S principle). No worries – fix and re-run.
However, because of the above complexity – using an kind of facade on top of the native platform – exceptions in Xamarin are sometimes not so straight forward (depending on the cause). Especially when a third party reference is causing errors on the specific platform or something else platform specific is happening. Let’s debug properly then!
Visual Studio Debug settings
Using Visual Studio (on PC or a virtual Windows on Mac/OSX) you need to load DLL information from everything in order of receiving the platform specific error all the way down from the app on the device.
- Go Debug menu > Options
- Now at Debugging > General in the options dialog
- “Enable Just My Code” should be OFF (unchecked)
- “Enable .NET Framework source stepping” should be ON (checked)
This will allow the errors to travel up to you when debugging. But wait – there’s more!
3rd party and custom DLLs
Additionally you might want to add your custom DLLs and libs such as Xamarin.Forms to the debug symbols.
Under Debugging > Symbols you can add the lib location containing DLLs and more importantly PDB – public debug symbols.
Just remember this doesn’t auto-update as you update your packages.
Runtime Exception Settings
While you now have loaded the DLLs from Xamarin and third party libs it’s not certain you’ll get the JIT debug handling for an uncaught exception, so you can actually see what’s going on when it’s happening. Work actively with Exception Settings. If this window is not available when debugging you can open it from the Debug menu > Windows > Exception Settings (CTRL+D, CTRL+E).
- Place a breakpoint at the last know “safe” location (for example before the app navigates)
- Start debugging and wait until you hit the breakpoint.
Remarks: the first time after starting VS will be slow since you’re now loading all those referenced DLLs + .Net.
- When VS breaks, check (click once) “Common Language Runtime Exceptions” in the Exception Settings window.
This is a 3-state checkbox which is usually filled (white with the cool dark theme) which means some errors are caught.
By checking it you catch all exceptions. This is normally not ideal since you will get all “soft” errors that normally don’t cause the app to crash so only do it when you know there’s an issue and restore it after by clicking again or right click in the window and choose “Restore defaults”.
Windows apps are a shortcut
It’s honestly common to leave out Windows, but as an Xamarin developer this might be a disadvantage. Remember the path errors travels above? Thing is that Windows 8.1 / Universal Windows Apps run directly on your machine – like an WPF app or more vaguely a website would. Meaning:
- No emulator needed (unless Phone) giving faster build / deploy
- Native exceptions (C#/.Net all the way)
This obviously doesn’t help you if there’s an issue on iOS / Android but if you share logic in a .net library or Xamarin.Forms catching the exception becomes greatly simplified – you don’t want to get that .net/C# exception from another platform when you can get it straight from your dev machine!
So even if the final product doesn’t include windows (but it might as well if you have it) debugging on “Window First” can accelerate your DevOps.