我是否必须实现UIViewController的IntPtr构造函数?

时间:2011-12-05 09:48:09

标签: c# garbage-collection xamarin.ios

这与我发布的另一个问题有关:What are my options to hunt Monotouch exceptions like "System.Exception: Selector invoked from objective-c on a managed object that has been GC'ed"?

我的测试人员和几乎所有的UIViewControllers都收到了崩溃报告,我得到的错误是:

System.Exception: Selector invoked from objective-c on a managed object that has been GC'ed ---> System.MissingMethodException: No constructor found for Browser.FolderListController::.ctor(System.IntPtr)

我不知道我做了一些明显错误的事情,我无法追查问题,但我知道在任何情况下我都不会覆盖 IntPtr 构造函数。问题是:我应该实施吗?这会让问题消失吗?如果ObjC使用这个构造函数复活GC控制器会有什么后果?

修改

我发现至少有一个原因,如果问题是遵循Rolf和Pupous的建议并设置一个线程,GC每秒10次,以便我可以强制崩溃。 我大量使用 NSNotificationCenter 。我在ViewDidLoad()注册我的观察员并在ViewDidUnload()中取消注册。 但是,如果通知到达manipulates the controller's view,则会执行该代码。 这意味着处理程序有可能触发 AFTER ViewDidDisappear()。如果视图恰好已经GC了,它就会崩溃。 我通过将我对NSNOtificatioCenter的订阅转移到ViewWillAppear()ViewWillDisappear()来修复它。

2 个答案:

答案 0 :(得分:3)

不,你不应该覆盖IntPtr构造函数。

您只会隐藏代码中的问题,而不是解决它们。

恢复GC控制器的一些(但不是全部)后果是:

  • 所有管理状态都将消失。您在原始控制器中拥有的任何(托管)变量将返回其原始状态(因为您现在有一个新的托管控制器实例)。
  • GC可能已经释放了控制器也有引用的任何其他对象(这可能包括诸如委托之类的事情,您无法轻松地重新创建。如果托管代理被释放然后被调用,您将最终非常难以追踪本机崩溃。)
  • 依赖于同步的托管对象和本机对象的任何内容都将具有未定义的行为(这可能包括您无法控制的MonoTouch内的代码)。

简而言之:你需要找出控制器被释放的确切原因,并防止这种情况发生。

如果需要临时解决方法,请创建静态列表并将控制器的所有实例放在该列表中。这将使用一些内存(当然,这取决于您创建的对象数量),但您不必处理未定义和不受支持的行为。

答案 1 :(得分:0)

当我使用IB Storyboard从我的主RootViewController推送新的DetailViewController时遇到了同样的问题。故事板已经有一个segue推送事件动作创建到故事板中的全新详细信息视图。但是,我需要根据单元格的内容动态推送不同的视图。无论如何,一旦我从Storyboard中删除了segue推送到DetailView并以编程方式尝试推送新的视图控制器,当我收到GC错误时。

我最终抓了故事板,只使用了普通的xib文件,并且能够完成同样的事情。我现在对使用Storyboard的GC进行了怀疑。

工具:Xcode 4.2.1& MonoDevelop 2.8.5