【问题标题】:iOS - core data - table view scroll to newly added recordiOS - 核心数据 - 表格视图滚动到新添加的记录
【发布时间】:2012-04-18 05:29:25
【问题描述】:

概述:

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

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

我想做的事:

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

我做了什么

  1. 添加新记录时,在NSFetchedResultsControllerDelegate方法内部,当类型为插入/更新/移动时,我将索引路径存储在属性lastAddedIndexPath
  2. 调用保存后,我滚动到“lastAddedIndexPath”

代码(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. 还有其他替代方法吗?

【问题讨论】:

  • 您的 [self.tableView endUpdates] 调用在哪里?您希望滚动在此之后发生。
  • 我在 controllerDidChangeContent 中执行滚动:我已重新编辑问题以显示代码。
  • 那么如果你切换滚动并且结束更新会发生什么?
  • 太棒了!!!!!!!非常感谢你,拯救了我的一天,我整天都在打破我的头。而问题是,在table view末尾添加新记录时,indexPath.row大于[self.tableView numberOfRowsInSection:indexPath.section],导致crash
  • 我会把它作为答案发布,然后!

标签: ios uitableview core-data nsfetchedresultscontroller


【解决方案1】:

您的滚动必须在[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 

    } 
} 

【讨论】:

    【解决方案2】:

    您应该执行滚动:

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

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

    【讨论】:

    • 谢谢,我在 controllerDidChangeContent: 内执行滚动,但似乎不起作用。已重新编辑问题以显示代码。让我试试 KVO。
    【解决方案3】:

    在我的场景中,我需要在表格视图顶部显示最后添加的对象,因此我使用了不同的方法,我使用 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 的table view 方法中,你可以使用这个数组来填充tableview。

    【讨论】:

    • 感谢 Shahid,但在我的情况下,我根据不同的字段对其进行排序,我无法更改排序顺序,所以我只想滚动到该记录
    • 可以使用这个方法scrollToRowAtIndexPath:atScrollPosition:animated:
    • 并在此之前排序您通常所做的事情。它将指向您最近添加的行
    猜你喜欢
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-13
    • 1970-01-01
    • 1970-01-01
    • 2014-02-17
    相关资源
    最近更新 更多