8

我有一个在 iOS 6 中使用 UIKit 状态保存的应用程序。我能够保存/恢复视图控制器的状态,即选择了哪个选项卡和导航控制器层次结构,但是我无法让我的表视图恢复它的偏移量。我的故事板中有一个用于视图以及视图控制器的恢复标识符,并且视图控制器(表的数据源)实现UIDataSourceModelAssociation如下:

- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)indexPath inView:(UIView *)view
{
    TSStatus *status = [self._fetchedResultsController objectAtIndexPath:indexPath];

    return status.objectID.URIRepresentation.absoluteString;
}

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view
{
    NSURL *statusURL = [NSURL URLWithString:identifier];
    NSManagedObjectID *statusID = [[TSDataController sharedController].persistentStoreCoordinator managedObjectIDForURIRepresentation:statusURL];
    TSStatus *status = (TSStatus *)[[TSDataController sharedController].mainContext objectWithID:statusID];

    return [__fetchedResultsController indexPathForObject:status];
}

modelIdentifierForElementAtIndexPath:inView:当应用程序进入后台时modelIdentifierForElementAtIndexPath:inView:被调用,但从未被调用。

4

4 回答 4

3

这不是您问题的真正答案,但我也无法让表格视图恢复其 contentOffset。

我猜这是 iOS 6 中的一个错误,因为文档明确指出 aUITableView恢复其 contentOffset,当 1)它有一个restorationIdentifier2)视图所属的视图控制器有一个restorationIdentifier和 3)数据源符合UIDataSourceModelAssociation协议。

但是,您可以在视图控制器中手动恢复 contentOffset 和所选项目:

- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
    [super encodeRestorableStateWithCoder:coder];

    [coder encodeObject:[NSValue valueWithCGPoint:self.tableView.contentOffset] forKey:@"tableView.contentOffset"];

    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    if (indexPath != nil) {
        NSString *modelIdentifier = [self modelIdentifierForElementAtIndexPath:indexPath inView:self.tableView];
        [coder encodeObject:modelIdentifier forKey:@"tableView.selectedModelIdentifier"];
    }
}

- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
    [super decodeRestorableStateWithCoder:coder];

    CGPoint contentOffset = [[coder decodeObjectForKey:@"tableView.contentOffset"] CGPointValue];
    self.tableView.contentOffset = contentOffset;

    NSString *modelIdentifier = [coder decodeObjectForKey:@"tableView.selectedModelIdentifier"];
    if (modelIdentifier != nil) {
        NSIndexPath *indexPath = [self indexPathForElementWithModelIdentifier:modelIdentifier inView:self.tableView];
        if (indexPath != nil) {
            [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
        }
    }
}

我不知道为什么UITableView不自动执行此操作,即使文档说它确实如此。如果有人知道答案,请发表评论。

于 2013-01-28T17:19:39.070 回答
3

如果 UITableView还设置了 restoreIdentifier,我发现这可以工作。

但是,如果 UITableViewController 在 UINavigationController 内,它就不起作用。已向 Apple 报告此问题,问题 ID:13536778。此问题似乎同时出现在 iOS 6.0 和 6.1.3 上。

于 2013-03-29T18:23:32.173 回答
2

这是 iOS 6 中的一个错误。

要使用UIDataSourceModelAssociation协议恢复表视图的状态,您应该-reloadData在返回有效索引路径之前调用表视图,-indexPathForElementWithModelIdentifier:inView:如下所示:

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view
{
    NSURL *statusURL = [NSURL URLWithString:identifier];
    NSManagedObjectID *statusID = [[TSDataController sharedController].persistentStoreCoordinator managedObjectIDForURIRepresentation:statusURL];
    TSStatus *status = (TSStatus *)[[TSDataController sharedController].mainContext objectWithID:statusID];

    [self.tableView reloadData];

    return [__fetchedResultsController indexPathForObject:status];
}
于 2013-05-05T20:01:22.837 回答
0

有关如何实现此目的,请参阅 Apple 的状态恢复示例。神奇的修复发生在decodeRestorableStateWithCoder方法中,调用reloadData

MyTableViewController.m

// this is called when the app is re-launched
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
    // important: don't affect our views just yet, we might not visible or we aren't the current
    // view controller, save off our ivars and restore our text view in viewWillAppear
    //
    NSLog(@"MyTableViewController: decodeRestorableStateWithCoder");

    [super decodeRestorableStateWithCoder:coder];

    self.tableView.editing = [coder decodeBoolForKey:kUnsavedEditStateKey];

    [self.tableView reloadData];
}

请注意,他们对编辑状态进行编码是很奇怪的,因为编辑在保存开始之前由他们的进入后台通知处理程序结束,因此它总是会恢复而不是编辑。他们也尝试设置self.tableView.editing而不是self.editing这样编辑按钮不会更新。还要注意关于不影响视图的评论,这首先是奇怪的,因为它们确实会影响视图,并且在解码状态之前调用第二个 viewWillAppear。鉴于这些错误,我不会使用此示例来调整您的编程技能。

另一个答案指出重新加载indexPathForElementWithModelIdentifier不是一个好主意,因为它被多次(至少两次)调用以查找可见和选定对象的各种索引路径。

于 2019-05-28T08:21:51.307 回答