2010-01-10 48 views
6

我最近刚刚完成了Stephen Kochan在Objective-C 2.0中的编程以及Erica Sadun的iPhone Cookbook的部分内容,这是iPhone开发和编程的新手。刚刚阅读本网站上回答的问题帮助了我很多,所以我非常感谢所有用户。现在我正在开发我的第一款iPhone应用程序,并且正在取得良好进展,除了一件让我难以置信的事情。可重新排序的UITableView,每部分最大行数

我在使用UITableView时遇到了一些麻烦。基本上,我有一个表格,每个部分最多需要6行,没有最小值(除非1行部分的行被删除,在这种情况下,部分与它一起)。该表也可以由用户重新排序。当用户将一行拖入一个已经有最多6个分配行的部分时,我希望该部分的最后一行将'budge'排序成为下一部分的第一行。

至于实现这个,我的第一个想法是调用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:,以及AppleView指南中提到的有点神秘的willMoveToRowAtIndexPath:fromIndexPath:方法,但在别的地方并不存在。

我在谷歌,本网站和苹果的文档中搜索了所有解决方案,但无济于事。

所以,简单地说一下我的问题,最好的方法是什么?我忽略了一些明显的东西吗?或者,我的实施概念是否从根本上来说是有缺陷的?

在此先感谢您的帮助!任何有识之士将不胜感激。

- 德鲁R.胡德

UPDATE:继他在他的回答评论乔丹的建议,我已经验证实际编辑数据源正在经历正常。当表格编辑块执行时,我现在总是得到错误Attempt to create two animations for cell(通过常识和断点验证时间)。所以我在编辑块中做错了什么。目前的代码完全如上所示。想法?

回答

0

所以,我终于解决了这个问题,并认为我会发布我在这里为了后代而做的。这很简单,真的:我只是将表中行的实际插入和删除移到了一个单独的方法中,然后在延迟后调用它。从一开始就已经很清楚了,约旦帮助我确认了在桌面上执行更新时发生的问题,而不是实际更改数据的过程。因此,这里的该诀窍代码:

-(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!"); 
} 

所有我需要做执行,这是添加该片段到我moveRowAtIndexPath:方法:

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

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

} 

所以我希望这有助于人谁可能有这个问题在未来。感谢乔丹和所有看过这个问题的人。 :)

2

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

我相信你需要更新数据源,然后才能删除行中的任何部分。因此,在此代码中,在删除之前,从Table_Array_Macro(我认为这是您的数据所在的位置)删除该行。

+0

感谢您的答复。它是,我做了 - 上面说:[[TABLE_ARRAY_MACRO objectAtIndex:i] removeLastObject]; [[TABLE_ARRAY_MACRO objectAtIndex:(i + 1)] insertObject:lastIcon atIndex:0] ;.为了澄清,我的数据源是一个数组数组(每个节一个数组),在这些数组中是包含表单元格实际信息的字典。 – FrigginGuy 2010-01-10 16:18:54

+0

尝试添加一个NSLog来统计前后的记录数。我很确定那里有不匹配的地方。这就是错误沟通的原因。 – Jordan 2010-01-10 17:49:44

+0

我遵循你的建议,我的数组正在根据需要进行更改。我确信这些计数和内容都能正确对应。一切都结束了。我现在得到的唯一错误是'尝试为单元格创建两个动画',所以看起来我的问题出现在我的编辑块中。 : - / – FrigginGuy 2010-01-12 02:32:27