找不到ViewController ::。ctor(System.IntPtr)的构造函数

时间:2011-04-11 14:57:48

标签: xamarin.ios

我遇到一个问题,我的Monotouch应用程序有时会在收到内存警告后崩溃。请看下面的堆栈跟踪。

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 

堆栈跟踪是正确的,因为指示的类(BoardController,它是一个UIViewController子类)缺少一个采用IntPtr参数的构造函数。但这是故意的,因为我在我的应用程序中根本不使用Interface Builder。那么为什么会这样呢?

我确实发现了一个类似的问题,似乎暗示如果您允许您的视图(或可能是视图控制器)变成垃圾回收,就会发生这种情况。但我不明白这是怎么发生的。一些背景知识:我的应用程序委托对导航控制器有强烈的引用,导航控制器又对导航堆栈中的根视图控制器进行强引用。此根视图控制器还拥有对BoardController实例的强引用。所以我不明白BoardController是如何收集垃圾的。

有什么想法吗?

1 个答案:

答案 0 :(得分:9)

当需要将本机对象浮出到托管对象时,使用IntPtr构造函数。在这种特殊情况下,您可以创建,如下所示:

 var foo = new Foo ();
 SomeObject.Property = foo;

这会将Foo对象分配给属性,但如果Property是Objective-C对象,如果你没有保留对“foo”的引用,那么Mono的GC将继续处理托管Foo和之间的链接。不受管理的Foo。

然后,稍后,您尝试检索它:

 var bar = SomeObject.Property;

在这里,MonoTouch将知道没有托管对象而不是映射到它,因此它必须构造一个新的托管对象,但它只有IntPtr到Objective-C代码。这就是你需要构造函数的原因。

您可能只想添加本机构造函数,这在很多情况中都很好,但如果您的对象在托管环境中存储了自己的状态,则会出现问题,例如:

 public class Foo : UIView {
     string Name;
     public Foo () { Name= "Hello"; }
     public Foo (IntPtr ptr) : base (ptr) {}
 }

在这种情况下,IntPtr构造函数不能仅从IntPtr完全重建托管对象及其状态。因此,问题的可能来源是您没有保留对象的引用。

所以真正的解决方法就是:在托管代码中保留对BoardController的引用,以防止在以后仍然使用它时收集对象。