从已经GC的托管对象上的objective-c调用的选择器,如何避免viewcontrollers被GC'd

Chr*_*vik 3 xamarin.ios

我们在appstore中有一个应用程序在iPhone 4g/4gs上没有任何问题,但是当我在iPod上测试时,我得到了一个惊喜,因为它在"随机"地方一直崩溃.看着strack的痕迹,我的视觉控制器似乎已经过了GC.

如果我写这样的方法,viewcontroller会被垃圾收集:

public void PushShowTeamController (Object a)
{
  var teamController = new TeamController (a);
  NavigationController.PushViewController (teamController, true);
}
Run Code Online (Sandbox Code Playgroud)

因为iPod突然抛出这样的错误:

 Jan  6 18:52:09 unknown MyApp[5197] <Warning>: Received memory warning.
 Jan  6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>: Unhandled Exception: System.Exception: Selector invoked from objective-c on a managed object that has been GC'ed ---> System.MissingMethodException: No constructor found for MyApp.TeamController::.ctor(System.IntPtr)
 Jan  6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>:   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 <filename unknown>:0 
 Jan  6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>:   at System.Activator.CreateInstance (System.Type type, System.Object[] args, System.Object[] activationAttributes) [0x00000] in <filename unknown>:0 
 Jan  6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>:   at System.Activator.CreateInstance (System.Type type, System.Object[] args) [0x00000] in <filename unknown>:0 
 Jan  6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>:   at MonoTouch.ObjCRuntime.Runtime.ConstructNSObject (IntPtr ptr, IntPtr klass) [0x00000] in <filename unknown>:0 
 Jan  6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>:   --- End of inner exception stack trace ---
Run Code Online (Sandbox Code Playgroud)

pou*_*pou 6


当处理托管对象时(当没有对实例进行引用时),并且该对象稍后由本机代码重新表面化时,将发生这种情况.

MyApp.TeamController只要本机代码需要(例如访问)引用,您就需要确保引用保留在托管代码中.

在大多数情况下,MonoTouch将确保保留参考.你的代码:

NavigationController.PushViewController (teamController, true);
Run Code Online (Sandbox Code Playgroud)

是正确的,UINavigationController并将继续参考你的teamController.但是,如果您调用PushViewController另一个控制器,则第一个引用将被覆盖,并且可由垃圾收集器(GC)收集.这种情况会导致你看到的例外情况.

注意:因为您无法预测GC何时将收集未引用的对象实例,所以异常将被随机抛出.