据我了解,我们需要在MonoTouch中处理它们时保持对Cocoa对象的引用。这样做的原因是ObjC运行时可能仍然保持对对象的引用,如果我们没有" MonoTouch引用"在它们上面,它们可以被垃圾收集,一旦ObjC运行时试图访问它们就会产生EXC_BAD_ACCESS
。
说,我们有两个UIViewController子类,VC1和VC2。如果用户单击VC1上的按钮,则UI导航到VC2,用户可以来回导航。如果我每次用户导航到VC2时都会创建一个新的VC2实例,那么对旧实例的引用就会丢失,因此它们会被垃圾收集,并且下次didReceiveMemoryWarning
传播到应用程序时应用程序会崩溃UIViewControllers。
如何发布旧引用,所以我不必每次都使用相同的VC2实例? Dispose
似乎还不够。
答案 0 :(得分:6)
据我了解,我们需要在MonoTouch中处理它们时保留对Cocoa对象的引用。
不完全。 MonoTouch 托管实例将保留对原生实例的引用。只要托管实例存在,原生实例将处于活动状态(因为它们是引用计数而MonoTouch不会释放它的引用)。
只要需要原生部分,您就需要保留对MonoTouch 托管实例的引用。
原因是ObjC运行时可能仍然保持对对象的引用......它们可能被垃圾收集,
Native(Objective C)实例是引用计数,而不是垃圾收集。原始实例在引用计数达到0之前不会被释放(当关联的托管实例存在时不会发生);
本机实例也可以保存对其他本机实例的引用。并非每个原生实例都有相应的托管实例。
一旦ObjC运行时尝试访问它们,就会产生EXC_BAD_ACCESS。
这不会发生,至少不是这样。 OTOH很难告诉你在你的情况下发生了什么(没有看到代码和/或崩溃)。
我怀疑您在完成作业之前(手动或非手动)处置托管实例。这是可能发生的简化:
UIView
); UIViewController
; UIViewController
将添加对原生 X的引用(原生引用计数== 2); MT.X
实例(例如,将变量设置为null
或其他实例); MT.X
垃圾收集器将处置托管实例,调用Dispose
将减少对< em> native X(本机引用计数== 1)。但 native 实例将不会被释放,因为视图控制器仍然引用它(而不是0); UIViewController
执行的操作本身就是X.ViewWillUnload
(例如,它会尝试加载新的UIView
); X
仍然存在(引用次数== 1),因此会调用它ViewWillUnload
,它会尝试返回托管实例...那是的设置即可。此问题的解决方案是确保在原生部分完成其工作之前,不要处置托管实例。
答案 1 :(得分:1)
我的应用程序中的情况相同,GC正确收集对象。换句话说,我从来没有遇到过简单地将VC引用归零并让GC完成其余工作的问题。
但是,我在调用Dispose
方法时遇到问题。看来我们不应该手动执行此操作。相反,我们应该等待GC收集对象并释放其资源。 Base NSObject
类在其终结器中调用Dispose
,因此在收集对象时将释放所有非托管资源。
您也可以在某些根VC的GC.Collect
方法中调用DidReceiveMemoryWarning
。