Bug 23767 - Using ForceLoad = true in an iOS binding project results in runtime error at launch on SIMULATOR ONLY: Failed to register the type 'System.Object'
Summary: Using ForceLoad = true in an iOS binding project results in runtime error at ...
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: XI 8.2.0
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: Untriaged
Assignee: Rolf Bjarne Kvinge [MSFT]
Depends on:
Reported: 2014-10-11 23:55 UTC by Matt Samet
Modified: 2014-10-14 14:40 UTC (History)
3 users (show)

Is this bug a regression?: ---
Last known good build:

Project with binding project exhibiting the bug. (961.95 KB, application/zip)
2014-10-11 23:55 UTC, Matt Samet

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Matt Samet 2014-10-11 23:55:05 UTC
Created attachment 8387 [details]
Project with binding project exhibiting the bug.

I'm posting this issue as response to this thread:

Since that forum post, I've discovered that the issue results from a binding project I made.  I've reproduced the issue with a minimal project, which I'm attaching here.

Here are my repro steps and current status:

I created a brand new iOS app project, from the single-view app template.  Launched on simulator, works fine.

I then added a reference to my binding project for the Pushbots library, and added one line to initialize the library during FinishedLaunching().

When testing this configuration on device, it works fine.  When testing on the iOS simulator, even before it gets to the FinishedLaunching method, it throws an exception: MonoTouch.RuntimeException: Failed to register the type 'System.Object'.

Full output of exception:

MonoTouch.RuntimeException: Failed to register the type 'System.Object'
  at MonoTouch.Registrar.DynamicRegistrar.GetMethodNoThrow (System.Type type, System.String selector) [0x0000e] in /Developer/MonoTouch/Source/maccore/src/ObjCRuntime/DynamicRegistrar.cs:675
  at MonoTouch.Registrar.DynamicRegistrar.GetMethodNoThrow (System.Type type, System.String selector) [0x00040] in /Developer/MonoTouch/Source/maccore/src/ObjCRuntime/DynamicRegistrar.cs:680
  at MonoTouch.Registrar.DynamicRegistrar.GetMethodNoThrow (System.Type type, System.String selector) [0x00040] in /Developer/MonoTouch/Source/maccore/src/ObjCRuntime/DynamicRegistrar.cs:680
  at MonoTouch.Registrar.DynamicRegistrar.GetMethodNoThrow (System.Type type, System.String selector) [0x00040] in /Developer/MonoTouch/Source/maccore/src/ObjCRuntime/DynamicRegistrar.cs:680
  at MonoTouch.Registrar.DynamicRegistrar.GetMethodDescriptionAndObject (System.Type type, IntPtr selector, IntPtr obj, Boolean throw_on_failure, System.IntPtr& mthis) [0x00007] in /Developer/MonoTouch/Source/maccore/src/ObjCRuntime/DynamicRegistrar.cs:619
  at MonoTouch.ObjCRuntime.Runtime.GetMethodAndObject (IntPtr klass, IntPtr sel, IntPtr obj, Boolean throw_on_failure, System.IntPtr& mthis) [0x00000] in /Developer/MonoTouch/Source/maccore/src/ObjCRuntime/Runtime.iOS.cs:230
  at at (wrapper native-to-managed) MonoTouch.ObjCRuntime.Runtime:GetMethodAndObject (intptr,intptr,intptr,int,intptr&)
  at at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
  at MonoTouch.UIKit.UIApplication.Main (System.String[] args, IntPtr principal, IntPtr delegate) [0x00005] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:62
  at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:46
  at testxam2.Application.Main (System.String[] args) [0x00008] in /Users/matt/Documents/Projects/Test Apps/testxam2/testxam2/Main.cs:17

This ONLY happens when in my Pushbots.linkwith.cs in the binding project, I have ForceLoad = true.  When I set it to false, or use SmartLink = true, I don't get this exception, however the Pushbots library doesn't seem to load at all and references in my code remain null after assignment to a "getInstance" singleton.

Everything works fine on an iOS 7 *device* and the library initializes and functions properly.  In Xcode (i.e. using the Pushbots framework as intended) everything works fine on simulator and device as well.

The Pushbots.a (coming from Pushbots.framework) lipo -info output is:
Architectures in the fat file: Pushbots.a are: i386 x86_64 armv7 arm64

The full build log is unremarkable and can be seen via the above forum link.

I've tried cleaning and rebuilding multiple times, and the issue can be triggered by simply changing ForceLoad to true in my Pushbots binding project.  If I have ForceLoad as false, or use SmartLink = true, Pushbots seems to not be loaded at all and references to it remain null after assignment.  All other code works however.

I've included my binding project in the attachment, the Pushbots header file from the framework is pretty simple (it's attached in there as well), and my ApiDefinition.cs file should be reflecting that.  That being said I'm not sure if the library requires some other binding attribute that I'm not familiar with as I'm not an iOS binding expert.  I actually used Objective Sharpie to come up with the initial version of the definition.

Configuration is: iOS 8 SDK, Xcode 6.0.1, OS X Mavericks 10.9.5, Xamarin.iOS (Indie), Xamarin Studio 5.5.227

Thanks for help with this!
Comment 1 Matt Samet 2014-10-12 00:02:26 UTC
I also realized after writing this that the Pushbots.linkwith.cs didn't reflect the actual architectures in the static library, HOWEVER after changing them to the appropriate values the bug STILL happens exactly the same.

These are the updated values:

LinkTarget.Simulator | LinkTarget.ArmV7 | LinkTarget.Simulator64 | LinkTarget.Arm64
Comment 2 Udham Singh 2014-10-13 04:14:18 UTC
I have checked this issue with sample app and instructions provided in bug description and observed the same behaviour mentioned in bug description.

Screencast : http://www.screencast.com/t/kqtfm9Xfg

Application Output : https://gist.github.com/Udham1/32c3ccae31a7f7d9be4f

Environment Info : 

=== Xamarin Studio ===

Version 5.5 (build 227)
Installation UUID: ce927b2a-2c07-44c5-b186-09cfdafba6dc
	Mono 3.10.0 ((detached/47db868)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 310000019

=== Apple Developer Tools ===

Xcode 6.0.1 (6528)
Build 6A317

=== Xamarin.iOS ===

Version: (Business Edition)
Hash: 959c1e4
Build date: 2014-10-03 00:25:37-0400

=== Build Information ===

Release ID: 505000227
Git revision: 7b721eeec7a2fa4c4f4de0ecd2aed4dc25edac95
Build date: 2014-10-02 15:53:38-04
Xamarin addins: 99ed56b428b31eba1efaace4d82188d6f334e6ca

=== Operating System ===

Mac OS X 10.9.4
Darwin Xamarin76s-Mac-mini.local 13.3.0 Darwin Kernel Version 13.3.0
    Tue Jun  3 21:27:35 PDT 2014
    root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64
Comment 3 Rolf Bjarne Kvinge [MSFT] 2014-10-14 11:11:34 UTC
The problem is that the Pushbots vendor provides its own implementation of application:didFinishLaunchingWithOptions:, but when they try to call your version, they don't do it correctly (somehow we end up looking for the managed method implementing application:developer_didFinishLaunchingWithOptions:, which doesn't exist).

There are a few options:

* Add --registrar:static to the additional mtouch arguments. This will make your simulator build work like your device build, but it will slow down the build.

* Implement the method Pushbots is looking for, by implementing your FinishedLaunching like this:

	[Export ("application:developer_didFinishLaunchingWithOptions:")]
	public new bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)

		return true;
Comment 4 Matt Samet 2014-10-14 14:40:17 UTC
Thanks!  After looking at this some more, I realize what's going on.

Pushbots is swizzling UIApplicationDelegate methods (they want to provide their own implementation of didFinishLaunching, didRegisterForRemoteNotifications, and a few others).

It seems like they are swizzling UIApplication's setDelegate with their own at static initialization time ([UIApplication load]) and then in that function, they swizzle a bunch more and replace them with stubs that call their own, and then call the developer's versions (i.e. developer_SELECTORNAME).

Your 2nd fix was the one I tried on my sample project, and that worked.  However I had to replicate that same fix for some of the other swizzled methods I was using on my *main* project which has a bit more going on in the AppDelegate.

I'm not sure if this info would be useful to someone else who has to deal with swizzled methods when doing a binding, but there didn't seem to be any docs referencing this issue.  You guys may want to write something up about it.

Thanks again.