Obtengo EXC_BAD_ACCESS tratando de usar mi subclase de UITableViewController

Estoy tratando de incorporar y modificar los encabezados de sección en expansión de WWDC 2010 vol128 Mastering Table Views. Sin embargo, debo haber perdido un paso u olvidado algo porque obtengo el error EXC_BAD_ACCESS cuando intento acceder a mi vista con la vista de tabla.

Olvidé dónde puede encontrar el código fuente, pero está en su sitio web para desarrolladores. Es mucho código para publicar.

La principal diferencia que veo es que su versión agrega la subclase de UITableViewController como una subvista a su appdelegate, es decir. ventana. Quiero agregar mi controlador a mi vista de desplazamiento que está en un controlador de vista. Estoy seguro de que hay un problema por eso.

El original a continuación no tiene sentido para mí porque libera el aTableViewController antes de agregarlo como una subvista, lo que en mi versión no puedo hacer. También hace self.tableViewController = aTableViewController; el tableViewController se sintetiza en la parte superior así: @synthesize tableViewController=tableViewController_ No sé de dónde viene ya que no se hace referencia en ningún otro lugar del proyecto. Nuevamente, el original tenía este código en el delegado de la aplicación, así que tal vez haya algo que no sé que está sucediendo allí.

Código de Apple (funciona):

 TableViewController* aTableViewController = [[TableViewController alloc] initWithStyle:UITableViewStylePlain];
    aTableViewController.plays = self.plays;
    self.tableViewController = aTableViewController;
    [aTableViewController release];

    // Stamdard window display.
    [self.window addSubview:aTableViewController.view];
    [self.window makeKeyAndVisible];

Para fines de prueba, hice una subclase testTableViewController vacía que está prácticamente vacía, e intenté agregarla como una subvista con el mismo resultado. Quizás, estoy creando una subclase UITableViewController incorrectamente. Lo siento, por ser vago, pero creo que tiene algo que ver con el fragmento de información proporcionado anteriormente.

Muchas Gracias

preguntado el 28 de agosto de 11 a las 03:08

Mencionas esta línea de código: @synthesize tableViewController=tableViewController_. ¿También podría pegar la declaración de propiedad, que debería verse así: @property (nonatomic, retain) tableViewController; -

Además, pegue la línea de código (y algo de contexto) donde obtiene el error. -

duh, lo olvidé por completo. Gracias. Ya no choca. Todavía tengo curiosidad por saber por qué self.tableViewController = aTableViewController me permite liberar aTableViewController antes de que se agregue como subView. -

Esa es una buena pregunta con una respuesta simple, y a la que debe prestar mucha atención, porque las propiedades de objetivo-c harán que su vida en un mundo no administrado sea un millón de veces más fácil. si la declaración de propiedad dice @property (nonatomic, retain) ... luego, estableciendo el valor con instanceName.propertyName = ..., el valor asignado a la propiedad será automáticamente retenido. Consulte los documentos de introducción: developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… -

Gracias. Agréguelo como respuesta y lo elegiré;) -

2 Respuestas

Los controladores de vista no son retenidos por sus vistas; entre otras razones, esto evita referencias circulares que harían problemática la desasignación. :] Debe conservar el controlador de vista usted mismo. Si la propiedad que declaró (self.tableViewController) no retiene el VC, agregará la vista a la ventana, pero luego el VC (¡el delegado de la vista para un montón de eventos!) Se desasignará, y luego obtener EXC_BAD_ACCESS aleatorio.

El código que incluyó en su pregunta parece que su VC se desasignaría incluso antes de agregar la vista a la ventana. Supongo que se deshizo del bloqueo arreglando esa propiedad para asegurarse de que se retenga el VC.

Respondido 28 ago 11, 08:08

Para responder esto:

El original a continuación no tiene sentido para mí porque libera el aTableViewController antes de agregarlo como una subvista

Mencionaste:

también hace self.tableViewController = aTableViewController; el tableViewController se sintetiza en la parte superior de esta manera: @synthesize tableViewController = tableViewController_ No sé de dónde viene ya que no se hace referencia en ningún otro lugar del proyecto.

Lo más probable es que si miras en el archivo de encabezado, verás una línea como esta:

@property (nonatomic, retain) tableViewController;

Esta es una "propiedad declarada" en Objective-C. Las propiedades declaradas proporcionan una forma superconveniente de obtener / configurar ivars con patrones comunes (como retener cualquier valor asignado).

De la documentación:

La función de propiedades declaradas de Objective-C proporciona una forma sencilla de declarar e implementar los métodos de acceso de un objeto.

Definitivamente debería leer la documentación de introducción aquí:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html

Las propiedades envuelven un montón de patrones comunes de formas probadas y verdaderas.

Por ejemplo, considere la implementación potencial (ingenua) de alguien de un método setter que retiene automáticamente el valor que se le asigna:

- (void) setSomeIvar:(SomeObject *)value
{
     [ivarValue release];
     ivarValue = [value retain];
}

Esto parece correcto a primera vista, pero considere el siguiente fragmento de código:

1: SomeObject * foo = [SomeObject new];
2: [bar setSomeIvar:foo];
3: [foo release];
...

(más tarde, potencialmente en algún otro método, donde foo es el mismo foo que arriba):

4: [bar setSomeIvar:foo];

¿Qué pasaría aquí? Bueno, en la línea 1, el recuento de retención es +1, en la línea 2, es +2, línea 3, +1, luego, más tarde, en la línea 4, liberamos inadvertidamente el objeto antes de asignarlo al ivar y retenerlo , por lo que este código generaría un error en esa línea.

El código más correcto sería algo como:

- (void) setSomeIvar:(SomeObject *)value
{
     if (ivarValue == value) return;
     [ivarValue release];
     ivarValue = [value retain];
}

Sin embargo, los patrones van más allá incluso de este ejemplo simplista.

Por lo tanto, las propiedades son súper convenientes y envuelven toda esta complejidad en algo más confiable y legible de lo que sería posible de otra manera.

También hacen que sea mucho más fácil asegurarse de que está liberando todo lo que se supone que debe estar en su dealloc método. Simplemente mire el archivo de encabezado para todas las propiedades marcadas (... retener ...) y asegúrese de que se publiquen en el dealloc. También por UIViewControllers en particular, y sus subclases, cualquier propiedad retenida marcada con IBOutlet debe configurarse para nil in viewDidUnload.

Cuando comencé a usar Objective-C, realmente no usaba propiedades, y sufrí por eso. Una vez que los entendí y comencé a usarlos, me hicieron la vida MUCHO más fácil.

Respondido 28 ago 11, 08:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.