10 January 2015

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

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 ;)

3 comments:

Kenneth Rasmussen said...

Thank you! Solved my problem. It is not easy to find this post though ;)

Joost van Schaik said...

@Kenneth glad it helped, sorry it was hard to find. I usually take a title that as exactly what I was looking for, but could not find. Any suggestions as to what you where searching for?

Kenneth Rasmussen said...

@Joost - in the end i searched for "xamarin pcl filenotfoundexception", which yielded this post as 3rd result, but earlier search terms included:
* Could not load file or assembly or one of its dependencies
* xamarin ios pcl not found
* could not load file or assembly local

none of which returned this blog :)