2011-04-11 11 views
10

Tengo un problema por el que a veces la aplicación Monotouch se cuelga justo después de recibir una advertencia de memoria. Por favor, vea ese rastro de pila a continuación.No se ha encontrado ningún constructor para ViewController ::. Ctor (System.IntPtr)

 
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 

El seguimiento de pila es correcto en que la clase indicada (BoardController, que es una subclase UIViewController) carece de un constructor que toma un parámetro IntPtr. Pero esto es intencional ya que no uso Interface Builder en absoluto en mi aplicación. Entonces, ¿por qué pasa ésto?

Encontré una pregunta similar que parecía sugerir que esto puede suceder si permite que sus vistas (o posiblemente ver controladores) se conviertan en basura. Pero no veo cómo esto puede suceder aquí. Algunos antecedentes: el delegado de mi aplicación contiene una fuerte referencia a un controlador de navegación, que a su vez contiene una fuerte referencia al controlador de vista raíz en la pila de navegación. Este controlador de vista raíz también contiene una fuerte referencia a la instancia BoardController. Entonces no entiendo cómo es posible que BoardController obtenga basura recolectada.

¿Alguna idea?

Respuesta

9

El constructor IntPtr se utiliza cuando un objeto nativo necesita ser cubierto por un objeto administrado. En este caso particular, podría estar creando, de esta manera:

var foo = new Foo(); 
SomeObject.Property = foo; 

Esto asigna el objeto de Foo a la propiedad, pero si la propiedad es un objeto de Objective-C, si no mantiene una referencia a "foo ", entonces el GC de Mono continuará y dispondrá el enlace entre el Foo administrado y el Foo no administrado.

Luego, más adelante, intenta recuperarlo:

var bar = SomeObject.Property; 

Aquí, MonoTouch sabrá que no hay ningún objeto gestionado más que un simple mapa a la misma, por lo que tiene que construir una nueva, pero todos tiene es el IntPtr al código de Objective-C. Es por eso que necesitas el constructor.

Usted puede verse tentado a simplemente añadir el constructor nativa, y esto está muy bien en muchos casos, pero es un problema si el objeto tiene su propio estado almacenado en el mundo administrado, por ejemplo:

public class Foo : UIView { 
    string Name; 
    public Foo() { Name= "Hello"; } 
    public Foo (IntPtr ptr) : base (ptr) {} 
} 

En este caso, el constructor IntPtr no puede reconstruir completamente el objeto gestionado y su estado simplemente desde el IntPtr. Entonces, la fuente probable de su problema es que no está manteniendo una referencia a su objeto.

Por lo tanto, la verdadera solución en resumen es: mantenga una referencia a su BoardController en su código administrado para evitar que el objeto se recopile cuando todavía lo vaya a usar más adelante.

+0

GRACIAS. TÚ. MIGUEL !!!! Había estado luchando con esto por años. Obtuve un controlador de navegación funky nav/tab/single/dialog root que cambia la lógica + los controladores modales, y acabo de pasar demasiado tiempo jugando con esas cosas pensando que esa fue la causa. No sé qué me llevó tanto googlear el mensaje de excepción ... ¡pero ahora todo tiene sentido! – Tyson

Cuestiones relacionadas