据我了解,在 MonoTouch 中处理 Cocoa 对象时,我们需要保存对它们的引用。
不完全的。MonoTouch托管实例将保留对本机实例的引用。只要托管实例存在,本机实例就会处于活动状态(因为它们被引用计数并且 MonoTouch 不会释放它的引用)。
IOW 您需要保留对 MonoTouch托管实例的引用,只要它们的本机部分是必需的。
这样做的原因是 ObjC 运行时可能仍然持有对对象的引用......它们可能被垃圾收集,
本机(Objective C)实例是引用计数的,而不是垃圾收集的。本地实例在其引用计数达到 0之前不会被释放(当关联的托管实例存在时不会发生这种情况);
本机实例也可以保存对其他本机实例的引用。并非每个本机实例都有相应的托管实例。
一旦 ObjC 运行时尝试访问它们,就会导致 EXC_BAD_ACCESS。
这不会发生,至少不会这样。OTOH 很难告诉您您的情况发生了什么(没有看到代码和/或崩溃)。
我怀疑您在托管实例完成工作之前正在处理(手动或不手动)您的托管实例。以下是可能发生的情况的简化:
- 您创建一个托管MT.X 实例(例如一个
UIView
);
- 这将创建并引用本机X(本机引用计数 == 1);
- 您在 MT.X 上覆盖一个事件(或添加一个委托......)“ViewWillUnload”(它本身也存在);
- 您将 MT.X 实例分配给另一个(托管)实例,例如
UIViewController
;
- 本机
UIViewController
将添加对本机X 的引用(本机引用计数 == 2);
- 应用程序执行愉快...
- 您停止引用该
MT.X
实例(例如将变量设置为null
或不同的实例);
- 由于不再引用
MT.X
垃圾收集器将处理托管实例,调用Dispose
这将减少对本机X 的引用(本机引用计数 == 1)。但是本机实例不会被释放,因为它仍然被视图控制器引用(不是 0);
UIViewController
做一些本机触发的事情X.ViewWillUnload
(例如,它试图加载一个新的UIView
);
- 因为
X
仍然存在于本机(ref count == 1),它会调用它ViewWillUnload
,它会尝试回到托管实例......被释放。
此问题的解决方案是确保在托管实例的本机部分完成其工作之前,您不会处置托管实例。