Я новичок в разработке для iPhone и программировании в целом, недавно завершив Программирование Стивена Кочана в Objective-C 2.0 и части поваренной книги Эрики Садун для iPhone. Просто чтение ответов на вопросы на этом сайте мне очень помогло, поэтому я благодарен всем его пользователям. Сейчас я работаю над своим первым приложением для iPhone и добиваюсь значительных успехов, за исключением одной вещи, которая поставила меня в тупик.
У меня возникли проблемы с UITableView. По сути, у меня есть таблица, в которой должно быть максимум 6 строк на раздел без минимума (за исключением случаев, когда строка раздела из 1 строки удаляется, и в этом случае раздел согласуется с ней). Таблица также может быть переупорядочена пользователем. Когда пользователь перетаскивает строку в раздел, в котором уже есть максимум 6 выделенных строк, я хочу, чтобы нижняя строка этого раздела сортировалась по «бюджету» вниз, чтобы стать верхней строкой следующего раздела.
Что касается реализации этого, моей первой мыслью было вызвать в tableView:moveRowAtIndexPath:toIndexPath:
метод, который будет проходить через разделы в цикле, убедившись, что ни один из них не имеет 7+ строк, корректируя массив по мере необходимости, а затем используя [myTable beginUpdates]
блок для удаления и вставки необходимых строк. Вот как все это выглядит (примечание: моя структура массива такова: Массив (Таблица)> Массивы (Разделы)> Словари (Элементы)):
-(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!");
}
Проблема в том, что когда я запускаю это, оно неизменно выдает исключение; это дает мне либо 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.)
, либо Attempted to create two animations for cell
, в зависимости от того, какую настройку я пытаюсь выполнить. Что касается этих настроек, я также попытался использовать reloadSections:withRowAnimation:
и, конечно, простой [editTable reloadData]
. Я попытался поместить вызов этого метода в соответствующие методы делегата / источника данных TableView, включая targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:
, и несколько загадочный метод willMoveToRowAtIndexPath:fromIndexPath:
, который упоминается в руководстве Apple по TableViews, но отсутствует в других местах.
Я искал в Google, на этом сайте и в документах Apple какие-либо предположения, но безрезультатно.
Итак, проще говоря, как лучше всего это сделать? Есть ли что-то очевидное, что я упускаю из виду? Или моя концепция реализации просто в корне ошибочна с самого начала?
Заранее спасибо за помощь! Любое понимание будет высоко ценится.
- Дрю Р. Худ
ОБНОВЛЕНИЕ: Следуя совету Джордана из его комментария к его ответу, я убедился, что фактические изменения в источнике данных проходят правильно. Теперь я последовательно получаю сообщение об ошибке Attempt to create two animations for cell
при выполнении блока редактирования таблицы (это время проверено здравым смыслом и точками останова). Так что я делаю что-то не так в своем блоке редактирования. Текущий код для этого точно так, как показано выше. Идеи?