我有一个UITableView,它从webService加载其数据。我有一个单例对象来跟踪我的数据(NSMutableArray *)
。加载新数据时,我向tableViewController发送通知并调用[self.tableView reloadData];
这将重绘我的表并使用当前数据填充单元格。
我有2个问题。
如果我在重新加载数据时滚动,应用程序崩溃,因为(NSMutableArray *)在加载新数据时空了一秒钟,我得到index 4 beyond bounds for empty array
为了解决这个问题,我在调用[_myArray removeAllObjects];
来修复崩溃之前完成了这个[self.tableView reloadData];
,但是在再次绘制它们之前清除所有单元格一秒钟。
这不是我想达到的预期效果。我希望它像邮件App一样重新加载单元格,它将绘制和删除必要的单元格,并保留单独保留的单元格。
我也尝试了reloadSections:withRowAnimation:UITableViewRowAnimationFade;
动画重新加载,但我仍然需要在重新加载之前清空数组。
我该怎么做?我觉得我需要创建一个数组的副本,然后移动它,我是在正确的道路上吗?这是我的重装功能。
- (void)reloadTable:(NSNotification *)notif {
[self.sellingTableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
}
******* **** UPDATE
在@oren的指导下,这就是我想出来的......这样可行,但我担心有大量数据的表,这样效率不够高。我试着编写一个散列算法来保存和索引行的比较,以减少迭代次数,但是结果集的排序总是存在差异......
我最终有2个名单。一个是我用来填充表的单例列表。这用于代替使用SQLite 3的核心数据等本地数据存储,但这些也可用于在应用关闭时保留数据。
当我唤醒我的应用程序或加载视图时..数据从我的单例列表中加载...然后我创建另一个数组,其中包含来自服务器的数据,检查两个数组是否相互更改,然后添加/删除行必要时。
-(void)sortRequestList:(NSNotification *)notification
{
RequestManager *newListManager = [[RequestManager alloc] init];
if ([notification.object isKindOfClass:[RequestManager class]])
{
newListManager = [notification object];//New Data that was downloaded from web
}
else
{
NSLog(@"Error, object not recognized.");
}
NSLog(@"newListManager count = %lu", (unsigned long)newListManager.requestNotFilledList.count);
NSLog(@"Before - requestNotFilledList count = %lu", (unsigned long)self.requestManager.requestNotFilledList.count);
NSMutableArray *insertIndexPaths = [[NSMutableArray alloc] init];
NSMutableArray *deleteIndexPaths = [[NSMutableArray alloc] init];
if ([self.requestManager.requestNotFilledList count] == 0)
{
[newListManager.requestNotFilledList enumerateObjectsUsingBlock:^(Request *request, NSUInteger index, BOOL *stop) {
[self.requestManager.requestNotFilledList insertObject:request atIndex:index];
[insertIndexPaths addObject:[NSIndexPath indexPathForRow:index inSection:0]];
}];
} else {
__block BOOL foundMatch;
[self.requestManager.requestNotFilledList enumerateObjectsUsingBlock:^(Request *oldReq, NSUInteger index, BOOL *stop) {
foundMatch = false;
[newListManager.requestNotFilledList enumerateObjectsUsingBlock:^(Request *newReq, NSUInteger newIdx, BOOL *stop) {
if ([oldReq.requestID isEqualToString:newReq.requestID])
{
foundMatch = true;
*stop = YES;
}
}];
if (foundMatch == false)
{
[deleteIndexPaths addObject:[NSIndexPath indexPathForRow:index inSection:0]];
[self.requestManager.requestNotFilledList removeObjectAtIndex:index];
}
}];
[newListManager.requestNotFilledList enumerateObjectsUsingBlock:^(Request *newReq, NSUInteger index, BOOL *stop) {
foundMatch = false;
[self.requestManager.requestNotFilledList enumerateObjectsUsingBlock:^(Request *oldReq, NSUInteger oldIdx, BOOL *stop) {
if ([oldReq.requestID isEqualToString:newReq.requestID])
{
foundMatch = true;
*stop = YES;
}
}];
if (foundMatch == false)
{
[insertIndexPaths addObject:[NSIndexPath indexPathForRow:index inSection:0]];
[self.requestManager.requestNotFilledList insertObject:newReq atIndex:index];
}
}];
}
NSLog(@"After - requestNotFilledList count = %lu", (unsigned long)self.requestManager.requestNotFilledList.count);
UITableView *tv = (UITableView *)self.view;
[tv beginUpdates];
[tv insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationRight];
[tv deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationFade];
[tv endUpdates];
[self.refreshControl endRefreshing];
}
答案 0 :(得分:1)
如何插入新的indexPaths并删除不需要的带有动画的indexPaths:
- insertRowsAtIndexPaths:withRowAnimation:
- deleteRowsAtIndexPaths:withRowAnimation:
你需要删除一个indexPaths数组,让我们假设你有一个数组[1,2,3,6]并删除2和6,你需要为行1设置数组indexPaths和3.
此外,您需要有一个要插入的indexPaths数组:让我们假设您添加a,b,c,如下所示:[a, 1 , 3 ,b, c ,7],因此indexPaths将用于行 - 0,3,4。
我做了一个简单的代码只是为了一个例子:我的tableView中的起始数据是[1,2,3,4,5,6],在下面的代码中我将它更新为[1, new1 ,2, new2 ,3,5, new3 ,7]。棘手的部分是计算插入和删除的indextPaths。
- (void)updateTableView
{
[self.tableView beginUpdates];
// First remove the objects
[self.dataArray removeObjectAtIndex:5];
[self.dataArray removeObjectAtIndex:3];
NSArray *indexPathsToRemove = [NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:3 inSection:0],
[NSIndexPath indexPathForRow:5 inSection:0], nil];
// Insert the new ones
[self.dataArray insertObject:@"New data 3" atIndex:4];
[self.dataArray insertObject:@"New data 2" atIndex:2];
[self.dataArray insertObject:@"New data 1" atIndex:1];
NSArray *indexPathsToInsert = [NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:1 inSection:0],
[NSIndexPath indexPathForRow:3 inSection:0],
[NSIndexPath indexPathForRow:6 inSection:0], nil];
// Animate the insertion and deletion
[self.tableView deleteRowsAtIndexPaths:indexPathsToRemove withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
}
您总是需要在插入之前考虑删除,在动画块中通过' beginUpdats',tableView不会插入新的行或部分,直到它处理完所有删除。