我有一个问题,我的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) [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如何可以收集垃圾.
有任何想法吗?
解决方法
当本地对象需要浮出一个被管理对象时,使用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完全重建被管理对象及其状态.所以您的问题的可能来源是您不保留对您的对象的引用.