I'm having an issue where my Monotouch application sometimes crashes just after receiving a memory warning. Please see that stack trace below.
Received memory warning. Level=2 DTMobileIS[2299] : _memoryNotification : { OSMemoryNotificationLevel = 2; timestamp = "2011-04-11 14:29:09 +0000"; } Toplevel exception: System.MissingMethodException: No constructor found for Myapp.UI.BoardController::.ctor(System.IntPtr) at System.Activator.CreateInstance (System.Type type, BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes) [0x00000] in :0 at System.Activator.CreateInstance (System.Type type, System.Object[] args, System.Object[] activationAttributes) [0x00000] in :0 at System.Activator.CreateInstance (System.Type type, System.Object[] args) [0x00000] in :0 at MonoTouch.ObjCRuntime.Runtime.ConstructNSObject (IntPtr ptr, IntPtr klass) [0x00000] in :0 at MonoTouch.ObjCRuntime.Runtime.GetNSObject (IntPtr ptr) [0x00000] in :0 at MonoTouch.ObjCRuntime.Runtime.GetNSObjectWrapped (IntPtr ptr) [0x00000] in :0 at (wrapper native-to-managed) MonoTouch.ObjCRuntime.Runtime:GetNSObjectWrapped (intptr) at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00000] in :0 at Myapp.Free.Application.Main (System.String[] args) [0x00000] in /Users/haakon/Code/Myapp-work/iOS/Myapp.Free/Myapp.Free/Main.cs:12
The stack trace is correct in that the indicated class (BoardController, which is a UIViewController subclass) lacks a constructor taking a IntPtr parameter. But this is intentional as I don't use Interface Builder at all in my application. So why does this happen?
I did find a similar question that seemed to suggest that this can happen if you allow your views (or possibly view controllers) to become garbage collected. But I don't see how this can happen here. Some background: My application delegate holds a strong reference to a navigation controller, which in turn holds a strong reference to the root view controller in the navigation stack. This root view controller also holds a strong reference to the BoardController instance. So I don't understand how it's possible that BoardController gets garbage collected.
Any ideas?
The IntPtr constructor is used when a native object needs to be surfaced to a managed object. In this particular case, you could be creating, like this:
var foo = new Foo ();
SomeObject.Property = foo;
This assigns the Foo object to the property, but if the Property is an Objective-C object, if you do not keep a reference to "foo", then Mono's GC will go ahead and dispose the linkage between the managed Foo and the unmanaged Foo.
Then, later on, you try to retrieve it:
var bar = SomeObject.Property;
Here, MonoTouch will know that there is no managed object anymore than maps to it, so it has to construct a new one, but all it has is the IntPtr to the Objective-C code. This is why you need the constructor.
You might be tempted to just add the native constructor, and this is fine in many cases, but it is a problem if your object has its own state stored in the managed world, for example:
public class Foo : UIView {
string Name;
public Foo () { Name= "Hello"; }
public Foo (IntPtr ptr) : base (ptr) {}
}
In this case, the IntPtr constructor can not completely reconstruct the managed object and its state merely from the IntPtr. So the likely source of your problem is that you are not keeping a reference to your object.
So the real fix in short is: keep a reference to your BoardController in your managed code to prevent the object from being collected when you are still going to use it later on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With