2010-01-10 7 views
6

Soy nuevo en el desarrollo y la programación de iPhone en general, habiendo completado recientemente la Programación de Stephen Kochan en Objective-C 2.0 y partes del Recetario para iPhone de Erica Sadun. El solo hecho de leer las preguntas respondidas en este sitio me ha ayudado mucho, así que le debo un gran agradecimiento a todos sus usuarios. Ahora estoy trabajando en mi primera aplicación para iPhone y estoy progresando mucho, salvo por una cosa que me dejó perplejo.UITableView con posibilidad de reordenar con número máximo de filas según la sección

Tengo algunos problemas con una UITableView. Básicamente, tengo una tabla que necesita tener un máximo de 6 filas por sección, sin mínimo (excepto si se elimina la fila de una sección de 1 fila, en cuyo caso la sección va junto con ella). La tabla también puede ser reordenada por el usuario. Cuando el usuario arrastra una fila en una sección que ya tiene el máximo de 6 filas asignadas, quiero que la fila inferior de esa sección ordene -desde "mover hacia abajo" para convertirse en la fila superior de la siguiente sección.

En cuanto a la implementación de esto, mi primer pensamiento fue llamar a un método en tableView:moveRowAtIndexPath:toIndexPath: que pasaría por las secciones en un bucle, asegurándose de que ninguna de ellas tuviera más de 7 filas, ajustando la matriz según sea necesario y luego usando una [myTable beginUpdates] bloque para eliminar e insertar las filas requeridas. Esto es lo único que se parece a (nota: la estructura de mi matriz es: Array (Tabla)> Arrays (secciones)> Diccionarios (Items)):

-(void) tableView: (UITableView *) tableView moveRowAtIndexPath: (NSIndexPath *) from toIndexPath: (NSIndexPath *) to 
{ 
// Get the dictionary object for the icon. 
NSMutableDictionary *theIcon = [[[TABLE_ARRAY_MACRO objectAtIndex: from.section] objectAtIndex: from.row] mutableCopy]; 

// Now remove it from the old position, and insert it in the new one. 
[[TABLE_ARRAY_MACRO objectAtIndex: from.section] removeObjectAtIndex: from.row]; 
[[TABLE_ARRAY_MACRO objectAtIndex: to.section] insertObject: theIcon atIndex: to.row]; 

if ([[TABLE_ARRAY_MACRO objectAtIndex: to.section] count] > 6) 
      [self budgeRowsAtSection: to.section]; 

// Now we're done with the dictionary. 
[theIcon release]; 

if (PM_DEBUG_MODE) 
    NSLog(@"Pet moved!"); 
} 



-(void) budgeRowsAtSection: (NSUInteger) section 
{ 
    if (PM_DEBUG_MODE) 
    NSLog(@"Budging rows..."); 

    // Set up an array to hold the index paths of the cells to move. 
    NSMutableArray *budgeFrom = [[NSMutableArray alloc] init]; 
    NSMutableArray *budgeTo = [[NSMutableArray alloc] init]; 

    // Start at the current section, and enumerate down to the nearest page with < 6 items. 
    int i = section; 

while (i < [TABLE_ARRAY_MACRO count]) { 

    if (PM_DEBUG_MODE) 
     NSLog(@"Attempting to budge rows in section %i!", i); 

    if ([[TABLE_ARRAY_MACRO objectAtIndex: i] count] > 6) { 

    // Grab the last object, and move it to the beginning of the next array. 
    NSMutableDictionary *lastIcon = [[[PET_ICON_DATA objectAtIndex: i] lastObject] mutableCopy]; 

    [[TABLE_ARRAY_MACRO objectAtIndex: i] removeLastObject]; 
    [[TABLE_ARRAY_MACRO objectAtIndex: (i + 1)] insertObject: lastIcon atIndex: 0]; 

    // Create an index path, and reflect the changes in the table. 
    [budgeFrom addObject: [NSIndexPath indexPathForRow: 6 inSection: i]]; 
    [budgeTo addObject: [NSIndexPath indexPathForRow: 0 inSection: (i + 1)]]; 

    // Now we're done with the icon. 
    [lastIcon release]; 

} 

if (PM_DEBUG_MODE) 
     NSLog(@"Rows budged for section %i!", i); 

++i; 

} 

    if (PM_DEBUG_MODE) 
    NSLog(@"From cells: %@\nTo cells: %@", budgeFrom, budgeTo); 

    if (PM_DEBUG_MODE) 
    NSLog(@"Data budged! Updating table..."); 

    [editTable beginUpdates]; 
    [editTable deleteRowsAtIndexPaths: budgeFrom withRowAnimation: UITableViewRowAnimationBottom]; 
    [editTable insertRowsAtIndexPaths: budgeTo withRowAnimation: UITableViewRowAnimationTop]; 
    [editTable endUpdates]; 

    [budgeFrom release]; 
    [budgeTo release]; 

    if (PM_DEBUG_MODE) 
    NSLog(@"Row budge done!"); 
} 

El problema es cuando corro esto, invariablemente, se emite una excepción; me da Invalid update: number of rows in section after update must be equal to number of rows before update, + or - the number inserted or deleted (etc.) o Attempted to create two animations for cell, dependiendo del ajuste que estoy intentando. En cuanto a cuáles son esos ajustes, también intenté usar reloadSections:withRowAnimation: y, por supuesto, un simple [editTable reloadData]. He intentado realizar la llamada a este método en los métodos delegados/fuente de datos TableView relevantes, incluido targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:, y el método un tanto misterioso willMoveToRowAtIndexPath:fromIndexPath: que se menciona en la guía de Apple en TableViews, pero no existe en ningún otro lugar.

He buscado en todo el Google, este sitio y en los documentos de Apple cualquier indicio de solución, pero fue en vano.

Entonces, para hacer mi pregunta simplemente, ¿cuál es la mejor manera de hacerlo? ¿Hay algo obvio que estoy pasando por alto? ¿O mi concepto de implementación es fundamentalmente defectuoso desde el principio?

¡Gracias de antemano por la ayuda! Cualquier idea sería muy apreciada.

- dibujó R. capilla

ACTUALIZACIÓN: Siguiendo el consejo de Jordan de su comentario en su respuesta, He verificado que los cambios reales a la fuente de datos van a través correctamente. Ahora obtengo sistemáticamente el error Attempt to create two animations for cell cuando se ejecuta el bloque de edición de tabla (ese tiempo verificado por el sentido común y los puntos de interrupción). Así que estoy haciendo algo mal en mi bloque de edición. El código actual para eso es exactamente como se muestra arriba. Ideas?

Respuesta

0

Así que finalmente resolví el problema y pensé en publicar lo que hice aquí por el bien de la posteridad. De hecho, es bastante simple: acabo de mover la inserción real y la eliminación de filas de la tabla a un método diferente, que luego invoqué después de un retraso. Había sido claro desde el principio, y Jordan me ayudó a confirmar, que el problema estaba ocurriendo al realizar las actualizaciones en la tabla en sí, en lugar de en el proceso de cambiar realmente los datos. Así que aquí está el código que hizo el truco:

-(void) performBudges 
{ 
if (PM_DEBUG_MODE) 
    NSLog(@"Performing budge animations..."); 

[editTable beginUpdates]; 
[editTable deleteRowsAtIndexPaths: budgeFrom withRowAnimation: UITableViewRowAnimationRight]; 
[editTable insertRowsAtIndexPaths: budgeTo withRowAnimation: UITableViewRowAnimationRight]; 
[editTable endUpdates]; 

[editTable performSelector: @selector(reloadData) withObject: nil afterDelay: 0.5]; 

[reloadedSections release]; 

[budgeFrom release]; 
[budgeTo release]; 

if (PM_DEBUG_MODE) 
    NSLog(@"Budges completed!"); 
} 

Y todo lo que tengo que hacer para llevar a cabo esto es añadir este fragmento en mi moveRowAtIndexPath: método:

if ([[PET_ICON_DATA objectAtIndex: to.section] count] > 6) { 

    [self budgeRowsAtSection: to.section]; 
    [self performSelector: @selector(performBudges) withObject: nil afterDelay: 1.0]; 

} 

así que espero que esto ayude a que puede tener este problema en el futuro Gracias a Jordan y a todos los que vieron esta pregunta. :)

2

[editTable beginUpdates]; [editTable deleteRowsAtIndexPaths: budgeFrom withRowAnimation: UITableViewRowAnimationBottom];
[editTable insertRowsAtIndexPaths: budgeTo withRowAnimation: UITableViewRowAnimationTop];
[editTable endUpdates];

Creo que necesita actualizar el DataSource antes de que realmente elimine la fila en cualquier sección que la esté eliminando.Entonces, en este código, antes de hacer la eliminación, elimine la fila de Table_Array_Macro (que creo que es donde están sus datos).

+0

Gracias por la respuesta. Es, y lo hice - arriba donde dice: [[TABLE_ARRAY_MACRO objectAtIndex: i] removeLastObject]; [[TABLE_ARRAY_MACRO objectAtIndex: (i + 1)] insertObject: lastIcon atIndex: 0] ;. Para aclarar, mi origen de datos es una matriz de matrices (una matriz por sección), y en esas matrices hay diccionarios que contienen la información real de las celdas de la tabla. – FrigginGuy

+0

Intente agregar un NSLog para contar el número de registros, antes y después. Estoy bastante seguro de que hay un desajuste allí. Eso es lo que el error se está comunicando. – Jordan

+0

Seguí tus consejos y mis matrices se modifican según sea necesario. Me aseguré de que tanto los recuentos como los contenidos correspondieran correctamente. Todo sale. El único error que obtengo ahora es el de "Intentar crear dos animaciones para la celda", por lo que parece que mi problema ocurre en mi bloque de edición. : - / – FrigginGuy

Cuestiones relacionadas