¿Cómo puedo completar un UITableView disperso a partir de un objeto de resultados obtenidos?

En mi dulce aplicación puedes usar dos tipos de elementos de una lista de elementos. Hay artículos equipables y artículos de bolsa. Cuando navega a la pantalla de inventario, hay dos secciones de una vista de tabla, cada una con 4 celdas. Cuatro celdas para artículos equipados y cuatro celdas para artículos en su "bolsa". Si no tienes nada equipado, las celdas simplemente dicen "vacías".

¿Cómo puedo completar las celdas de la tabla de forma condicional en función de la forma de mi objeto de resultados?

Aquí está el código que desearía tener:

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {

  static NSString *CellIdentifier = @"Cell";

  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  }

  // this returns 'nil' if the index path was out of bounds
  NSManagedObject * item = [self.fetchedResultsController carefullyGetObjectAtIndexPath:indexPath];

  if (nil == item) {
    cell.textLabel.text = @"empty"; 

  } else {
    cell.textLabel.text = [item valueForKey:@"name"];

  }

} 

Algunos problemas que he encontrado al intentar implementar este objectAtIndexPath 'cuidadoso':

Intenté verificar los límites, pero tengo problemas porque fetchedArray es plano, mientras que el modelo conceptual por el que trato de navegar no es plano: las filas son secciones 'en'.

Intenté usar un intento/atrapar, pero luego recordé que los elementos fuera de los límites no están definidos, no son nulos ... así que a veces recibo un error que puedo detectar y reaccionar, y a veces solo obtengo cosas interesantes al azar. . La configuración que tengo ahora:

@try {

  NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];

  return managedObject;
}
@catch (NSException * e) {
  return nil;
}

constantemente me da 5 entradas, 4 en los lugares correctos y 1 bola impar que es una repetición de la otra sección.

No estoy seguro de cómo navegar por los resultados obtenidos manualmente. Estoy jugando con cuatro elementos, 2 de cada tipo. Esperaba que fuera tan fácil como una matriz doblemente anidada, con secciones en el exterior y filas en el interior. Parece que las cosas son más complicadas que esto. Cuando inspecciono el NSArray de resultados obtenidos, veo que es plano. Todos los elementos de "bolsa" son los primeros, y los "equipables" vienen a continuación. Sin embargo, no creo que pueda depender de este orden, por lo que no me siento seguro haciendo una función de mapeo para pasar de la sección indexPath al índice de matriz. (Podría estar convencido de sentirme seguro acerca de esto).

Una alternativa que se me ocurrió consiste en llenar mi inventario con 8 artículos 'vacíos' que se devolverían como resultados de marcador de posición cuando las secciones no se llenen por completo. Aunque esto no me sienta bien.

Me doy cuenta de por qué esto no funciona: se supone que las tablas no deben tener filas 'vacías'. ¡Pero quiero que mi tabla tenga filas vacías!

ACTUALIZACIÓN

Aquí está el método que estoy usando por ahora...

- (NSManagedObject*) carefullyGetObjectAtIndexPath:(NSIndexPath*)indexPath 
{
  NSLog(@"in %@ %s", [self class], _cmd);

  NSString * desiredType = (indexPath.section == BAG_SECTION)? @"bag" : @"equipable";
  NSArray * fetchedObjects = [self.fetchedResultsController fetchedObjects];
  NSInteger sectionStartIndex = -1;

  // iterate until you hit a type you like
  NSUInteger i, count = [fetchedObjects count];
  for (i = 0; i < count; i++) {
    NSObject * obj = [fetchedObjects objectAtIndex:i];
    NSString * fetchedType = (NSString*)[obj valueForKey:@"type"];

    if ([desiredType isEqualToString:fetchedType]) {
      sectionStartIndex = i;
      break;
    }
  }

  if (-1 == sectionStartIndex) {
    // maybe there aren't any of that type of item

  } else {

    NSInteger calculatedEntityIndex = sectionStartIndex + indexPath.row;
    NSLog(@"calculated index %d", calculatedEntityIndex);

    // if we are still in the array
    if (calculatedEntityIndex < [fetchedObjects count]) {

      // then we can get the object
      NSManagedObject * entity = [fetchedObjects objectAtIndex:calculatedEntityIndex];

      // and if we are still in the right section
      NSString * typeForEntityAtIndex = [entity valueForKey:@"type"];

      if ([desiredType isEqualToString:typeForEntityAtIndex]) {
        // then this is what we wanted

        return entity;
      }
    }
  }

  return nil;   
}

Realmente no siento que deba repetir algo como esto...

z.

Divulgación completa: este es un proyecto a término, pero el proyecto es hacer la aplicación por cualquier medio necesario. Esto incluye bibliotecas de terceros, hacer preguntas sobre stackoverflow, etc.

preguntado el 01 de julio de 12 a las 05:07

Busque aquí vistas de tabla personalizadas, cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html -

1 Respuestas

Ziggy,

La NSFetchedResultsController tiene muchas limitaciones. Si no puede hacer que su esquema cumpla con los requisitos exactos y parece que probablemente no lo haya hecho, entonces debe construir su tableView de múltiples NSFetchRequests. Es sencillo. La mayoría de los interesantes tableViews hacer sólo esto. Core Data realmente funciona mejor cuando realiza búsquedas más grandes y luego refina la búsqueda usando las operaciones de configuración y filtro en las clases de colección.

tableViews puede tener filas vacías. Solo tiene que coordinar esto con el código personalizado en sus diversos códigos de configuración de celda y delegado.

Tienes muchas opciones para solucionar tu problema. Parece que no está satisfecho con una API de marco bastante limitada. Eres un programador en ciernes. Enrolla el tuyo.

Andrés

PD Tienes un objetivo curioso: escribir una aplicación para Mac OS X/iOS sin necesidad de aprender Objective-C. De hecho, ha elegido la única tecnología en el marco, Core Data, que ejercita Objective-C a su máxima capacidad. (En mi opinión, como educador de programadores de iOS, su educación probablemente sería mejor aprendiendo las complejidades de un modelo de persistencia muy diferente, el modelo de Core Data, que retirarse a la solución SQL estándar y mundana). Si prefiere usar un lenguaje diferente, MacRuby/RubyMotion es bastante efectivo.

Respondido 01 Jul 12, 16:07

¡Gran alimento para el pensamiento! Por cierto, no aprender Objective-C no era mi objetivo: me gusta Objective-C y me gusta aprender nuevos lenguajes. Solo quería aclarar que responder esta pregunta no entraría en conflicto con la etiqueta de tarea (ya que la pregunta surgió de la tarea y no era la tarea en sí). - Ziggy

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