iOS - 核心数据 - 表格视图滚动到新添加的记录

时间:2012-04-18 05:29:25

标签: ios uitableview core-data nsfetchedresultscontroller

概述:

我有一个iOS项目,其中包含以下内容:

  • 核心数据(使用NSFetchedResultsController
  • 在表格视图(UITableView
  • 中显示数据

我想做什么:

  • 当用户添加记录时,我想滚动到新添加的记录。

我做了什么

  1. 添加新记录时,在NSFetchedResultsControllerDelegate方法内,当类型为insert / update / move时,我将索引路径存储在属性lastAddedIndexPath
  2. 调用save后,我滚动到“lastAddedIndexPath”
  3. 代码(NSFetchedResultsControllerDelegate)

    - (void)controller:(NSFetchedResultsController *)controller
       didChangeObject:(id)anObject
           atIndexPath:(NSIndexPath *)indexPath
         forChangeType:(NSFetchedResultsChangeType)type
          newIndexPath:(NSIndexPath *)newIndexPath
    {       
        if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
        {
            switch(type)
            {
                case NSFetchedResultsChangeInsert:
                    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                    NSLog(@"going to store insert - scroll");
                    self.lastAddedIndexPath = newIndexPath;
                    break;
    
                case NSFetchedResultsChangeDelete:
                    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                    break;
    
                case NSFetchedResultsChangeUpdate:
                    [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                    NSLog(@"going to store update - scroll");
                    self.lastAddedIndexPath = newIndexPath;
                    break;
    
                case NSFetchedResultsChangeMove:
                    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                    NSLog(@"going to store move - scroll");
                    self.lastAddedIndexPath = newIndexPath;
                    break;
            }
        }
    }
    

    要滚动的代码

    - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
    {
        if (self.beganUpdates) //already [self.tableView beginUpdates] invoked
        {
            [self scrollToLastAddedIndexPath];  //contains the logic to scroll
            [self.tableView endUpdates];   
        }
    }
    

    问题

    • 我认为该记录是在另一个线程中异步添加到表视图中的。
    • 所以即使在保存数据库之后,当我滚动到lastAddedIndexPath时,表中的记录还不存在。

    问题

    1. 将记录添加到表格视图后,如何滚动到新添加的记录路径?
    2. 我应该使用通知来了解数据库的保存时间吗?
    3. 还有其他替代方法吗?

3 个答案:

答案 0 :(得分:5)

您的滚动必须在[self.tableView endUpdates]之后进行,因为在该点之前新行未添加到表中。所以切换两个语句:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{ 
    if (self.beganUpdates) //already [self.tableView beginUpdates] invoked 
    { 
        [self.tableView endUpdates]; 
        [self scrollToLastAddedIndexPath];  //contains the logic to scroll 

    } 
} 

答案 1 :(得分:1)

您应该执行滚动:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {

或者,您可以在添加新记录时通知KVO。

答案 2 :(得分:0)

在我的场景中,我需要在表视图的顶部显示最后添加的对象,所以我使用了不同的方法,我使用NSSortDescriptor对数组进行排序,然后每次添加/删除任何记录时重新加载表视图。像这样

NSSortDescriptor * sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO]autorelease];
NSArray * sortDescriptorArray = [[[NSArray alloc] initWithObjects:sortDescriptor,nil]autorelease];

self.commitsList =  [[self.listItem.itemCommit allObjects] sortedArrayUsingDescriptors:sortDescriptorArray];

[tblView reloadData];

然后,您可以在initWithKey中使用与您的数据相关的任何密钥,并对您的数组进行排序以解决此问题。 在表视图的CellForRowIndex方法中,您可以使用此数组填充tableview。