我遇到一个问题,我的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是如何收集垃圾的.
有任何想法吗?
当需要将本机对象浮出到托管对象时,使用IntPtr构造函数.在这种特殊情况下,您可以创建,如下所示:
var foo = new Foo ();
SomeObject.Property = foo;
Run Code Online (Sandbox Code Playgroud)
这将Foo对象分配给属性,但如果Property是Objective-C对象,如果你没有保留对"foo"的引用,那么Mono的GC将继续处理托管Foo和非托管Foo之间的链接.
然后,稍后,您尝试检索它:
var bar = SomeObject.Property;
Run Code Online (Sandbox Code Playgroud)
在这里,MonoTouch将知道没有托管对象而不是映射到它,因此它必须构造一个新的托管对象,但它只有IntPtr到Objective-C代码.这就是你需要构造函数的原因.
您可能想要添加本机构造函数,在许多情况下这很好,但如果您的对象在托管环境中存储了自己的状态,则会出现问题,例如:
public class Foo : UIView {
string Name;
public Foo () { Name= "Hello"; }
public Foo (IntPtr ptr) : base (ptr) {}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,IntPtr构造函数不能仅从IntPtr完全重建托管对象及其状态.因此,问题的可能来源是您没有保留对象的引用.
因此,真正的修复方法是:在托管代码中保留对BoardController的引用,以防止在以后仍在使用它时收集对象.
| 归档时间: |
|
| 查看次数: |
1991 次 |
| 最近记录: |