我是iPhone开发人员和编程人员的新手,最近完成了Stephen Kochan的Objective-C 2.0编程,以及部分Erica Sadun的iPhone Cookbook。仅阅读本网站上已回答的问题对我有很大帮助,因此,我要非常感谢它的所有用户。现在,我正在开发自己的第一个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委托(delegate)/数据源方法中,包括targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:
和Apple指南在TableViews中提到的有些神秘的willMoveToRowAtIndexPath:fromIndexPath:
方法,但在其他地方则不存在。我在Google,此站点和Apple的文档中进行了搜索,以寻找解决方案的任何线索,但无济于事。
因此,简单地说,解决此问题的最佳方法是什么?我有什么明显的事情要忽略吗?还是我的实现概念从一开始就存在根本缺陷?
先谢谢您的帮助!任何见解将不胜感激。
-德鲁·胡德(Drew R.Hood)
更新:根据约旦对他的回答的评论的建议,我已经验证了对数据源的实际编辑正在正确进行。现在,在执行表编辑块时,我始终收到错误
Attempt to create two animations for cell
(该时序由常识和断点验证)。所以我在编辑块中做错了什么。当前的代码与上面的代码完全相同。有想法吗? 最佳答案
我相信您实际上需要在要删除行的任何部分中删除行之前,先更新数据源。因此,在此代码中,执行删除操作之前,请从Table_Array_Macro(我认为这是您的数据所在的位置)中删除该行。