2010-10-09 66 views
4

我正在研究Feed阅读器iOS项目。以反向时间顺序在UITableView中列出供稿条目。启动时,它们从数据库加载到数组中。在同步上更新UITableView的模式?

当应用程序与提要同步时,它会为新的顺序创建一个新数组,然后更新表,将新数组与旧数组进行比较以确定要删除,更新或插入的单元格。我做这件事的方式是天真的,因此非常低效:大量调用indexOfObject:来查看一个数组中的项是否在另一个数组中。两次。对于每个新条目添加一次,以查看它是否在旧数组中,然后针对旧数组中的每个条目添加一次,以查看新数组中是否为而不是

作为一名数据库专业人员,此设计冒犯了我。

但它必须是一个很常见的模式。什么才是最合适的,充分的可可方法呢?

回答

4

原来我是在这个错误。我发现的解决方案是照常添加和删除阵列中的项目,然后根据需要为每个添加,更改或移动的行调用insertRowsAtIndexPaths:withRowAnimation:reloadRowsAtIndexPaths:withRowAnimation:deleteRowsAtIndexPaths:withRowAnimation:。我以前的计划中的错误是我应该等到所有的改变和完成,然后在beginUpdates/endUpdates区块中只调用一次这些方法。原来这个块实际上并不是必须的,因为修改方法可以在它们之外调用。

对于插入,更新或删除的每个单元格调用每个方法一次要比计算所有更改并一次提交更容易。太混乱,容易出错,而且效率低下,试图一次性完成。

因此,代码我结束了这个样子的:

if (parsedItem.savedState == ItemModelSavedStateInserted) { 
    // It's a new entry. Insert it. 
    [items addObject:parsedItem]; 
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:items.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationTop]; 
} else { 
    // It's an existing entry. Find it in the portal and move it, if necessary. 
    NSUInteger foundAt = [items 
     indexOfObject:parsedItem 
       inRange:NSMakeRange(currentItemIndex, items.count - currentItemIndex - 1) 
    ]; 
    if (foundAt == currentItemIndex) { 
     // It hasn't moved! 
     if (parsedItem.savedState == ItemModelSavedStateUpdated) { 
      // It was updated, so replace it. 
      [items replaceObjectAtIndex:currentItemIndex withObject:parsedItem]; 
      [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:currentItemIndex inSection:0]] withRowAnimation:UITableViewRowAnimationMiddle]; 
     } 
    } else { 
     // It has shifted position. 
     if (foundAt != NSNotFound) { 
      // It has moved. 
      [items removeObjectAtIndex:foundAt]; 
      [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:foundAt inSection:0]] withRowAnimation:UITableViewRowAnimationBottom]; 
     } 
     // Need to insert it. 
     [items insertObject:parsedItem atIndex:currentItemIndex]; 
     [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:currentItemIndex inSection:0]] withRowAnimation:UITableViewRowAnimationTop]; 
    } 
} 
1

考虑使用NSSets来区分当前项目集合和新项目集合,使用单个NSMutableArray来保存有序的当前列表。您可能希望从阵列中删除每个过期的项目,然后将每个未到期的新项目排入阵列。您不需要移除或放弃的项目是您可能需要更新的项目。