“System.IO.FileNotFoundException” using controls from another assembly in Xamarin Forms on iOS.

3 minute read

Disclaimer: I am at the early stages of learning Xamarin and may be just writing some stupid and obvious things. That’s just the way it is. This blog is as much a source of information as a it is a record of my learning process. I am a Windows Phone developer trying to make my code usable on other platforms.

I was building a solution as follows

  • I created a Xamarin solution XamarinPclControlBug for Windows Phone, Android and iOS using the “Blank App (Xamarin.Forms portable)” template.
  • I created a separate extra PCL PclControl that would hold some controls I was creating.
  • I then upgraded the whole solution to Forms 1.3.0 using this step-by-step procedure
  • I added references to PclControl in all four other projects of XamarinPclControlBug
  • I created a StartPage.xaml and made sure that was the start page in XamarinPclControlBug (portable) by setting MainPage to new StartPage() in de App constructor
  • I placed my custom control (and only that custom control) on StartPage.xaml
  • I deployed on Android and Windows Phone, and all was rosy.
  • I deployed on iOS, and I got:
    System.IO.FileNotFoundException: Could not load file or assembly 'PclControl' or one of its dependencies. The system cannot find the file specified.

You can check your references and deployment settings all you want, my friends, it turns out there’s probably a bug in Xamarin Forms’ iOS implementation. If you use controls and only controls from a PCL or dll that does not contain other code that is called from the app, apparently Xamarin on iOS ‘forgets’ to load/deploy the assembly (or something like that). But there is a work around.

In my sample solution I made a trivial control MyButton which is simply a child class of Button that does nothing special. The PCL PclControl contains this only this code:

using Xamarin.Forms;

namespace PclControl
{
  public class MyButton :  Button
  {
  }
}
Which allows me to use it in Xamarin Forms Xaml like this:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  xmlns:pclControl="clr-namespace:PclControl;assembly=PclControl"
  x:Class="XamarinPclControlBug.StartPage">
  <pclControl:MyButton Text="Click me" />
</ContentPage>

imagewp_ss_20150110_0001If you deploy this to Android, it looks good (albeit ugly), likewise in Windows Phone. It’s nothing special – just a button. But is you try to deploy this on iOS, this does not work at all, you get the System.IO.FileNotFoundException

 

 

 

 

The work around is as simple as it is weird. You go the iOS app’s AppDelegate class, and you add the code in that I displayed in red and underlined

using MonoTouch.Foundation;
using MonoTouch.UIKit;
using PclControl;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

namespace XamarinPclControlBug.iOS
{
  [Register("AppDelegate")]
  public partial class AppDelegate :
      FormsApplicationDelegate 
  {
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
      var b = new MyButton();
      Forms.Init();

      LoadApplication(new App()); 

      return base.FinishedLaunching(app, options);
    }
  }
}

imageIndeed – you make a manual fire-an-forget instance of the control that you want to use, and lo and behold on the right:

If you comment out the var b = new MyButton(); in the sample solution it will not work – if you do uncomment it, it will. Make sure you clean the solution before attempting re-deploy – I have noticed that sometimes making a little change like this is not enough to properly redeploy.

I think this is a bug, and one that took me quite some time to track and work around. Creating the control in code was just the result of testing whether the code could be compiled if I created a control from code – and then suddenly it worked, after hours of checking all kinds of settings. Living on the bleeding edge has it’s price.

UPDATE January 11, 2015

It has been brought to my attention that this is not caused by a bug but due to the behavior of the iOS linker. My brilliant Italian friend and fellow MVP Corrado Cavalli has run into the same or at least very similar problem earlier and has blogged about it as early as October, and recently this article from December by James Montemagno describes the same problem – and solution. Well, I can only hope my blog makes this issue (and the solution) easier to find, because I could not ;)