Я плохо знаком с iPhone dev и программирующий в целом, недавно завершив Программирование Stephen Kochan в Objective C 2.0, и части iPhone Cookbook Erica Sadun. Просто чтение вопросов, на которые отвечают, на этом сайте помогло мне много, таким образом, я должен большое спасибо всем его пользователям. Теперь я работаю над своим первым приложением для iPhone, и добиваюсь существенного прогресса, сохраняю, с одной стороны, этому озадачили меня.
Я испытываю некоторые затруднения из-за UITableView. В основном у меня есть таблица, которая должна иметь максимум 6 строк на раздел без минимума (кроме того, если строка раздела с 1 строкой удалена, в этом случае раздел соглашается с ним). Таблица может также быть переупорядочена пользователем. Когда пользователь перетаскивает строку в раздел, который уже имеет максимальные 6 выделенных строк, я хочу нижний ряд того раздела к виду - 'сдвигаются с места' вниз для становления верхним рядом следующего раздела.
Что касается реализации этого, моя первая мысль состояла в том, чтобы призвать метод tableView:moveRowAtIndexPath:toIndexPath:
это прошло бы разделы в цикле, удостоверившись, что ни один из них не имел 7 + строки, корректируя массив по мере необходимости, и затем с помощью a [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 для любого подозрения решения, но напрасно.
Так, для помещения моего вопроса просто, что лучший способ состоит в том, чтобы пойти об этом? Есть ли некоторая очевидная вещь, которую я пропускаю? Или мое понятие реализации просто существенно испорчено с самого начала?
Заранее спасибо за справку! Любое понимание очень ценилось бы.
- Drew R. Капот
ОБНОВЛЕНИЕ: Следуя совету Иордании из его комментария к его ответу, я проверил, что фактические редактирования к источнику данных проходят правильно. Я теперь последовательно получаю ошибку Attempt to create two animations for cell
когда блок редактирования таблицы выполняется (что, синхронизируя проверенный здравым смыслом и точками останова). Таким образом, я делаю что-то не так в своем блоке редактирования. Текущий код для этого точно как показано выше. Идеи?
Итак, я наконец-то решил проблему и подумал, что опубликую то, что я сделал здесь ради потомства. Это довольно просто, правда: я только что переместил фактическую вставку и удаление строк в таблицу в отдельный метод, который я тогда вызываю после задержки. С самого начала было ясно, и Джордан помог мне подтвердить, что проблема возникла при выполнении обновлений самой таблицы, а не в процессе фактически меняющихся данных. Итак, вот код, который сделал трюк:
-(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!");
}
и все, что я должен сделать, чтобы выполнить это, это добавить этот фрагмент в мою MOUROWATINDEXPATH:
Метод:
if ( [[PET_ICON_DATA objectAtIndex: to.section] count] > 6 ) {
[self budgeRowsAtSection: to.section];
[self performSelector: @selector(performBudges) withObject: nil afterDelay: 1.0];
}
Так что я надеюсь, что это поможет всем, кто может иметь это проблема в будущем. Благодаря Иорданию и всем, кто рассматривал этот вопрос. :)
[editTable beginUpdates]; [editTable deleteRowsAtIndexPaths: budgeFrom withRowAnimation: UITableViewRowAnimationBottom];
[editTable insertRowsAtIndexPaths: budgeTo withRowAnimation: UITableViewRowAnimationTop];
[editTable endUpdates];
Я считаю, что вам нужно обновить DataSource, прежде чем вы действительно удалите строку в том разделе, из которого вы ее удаляете. Итак, в этом коде, прежде чем выполнять удаление, удалите строку из Table_Array_Macro (где, как мне кажется, находятся ваши данные).