8

我目前正在仅 iOS6 的应用程序中实现自动状态保存/恢复。

为了恢复表视图,我将UIDataSourceModelAssociation协议添加到我的表视图控制器并实现

- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)idx inView:(UIView *)view

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view

当按下主页按钮时,状态保存方法(包括modelIdentifierForElementAtIndexPath:iView:)将按预期调用并返回给定索引路径的有效标识符字符串。

杀死应用程序并重新启动它时,状态恢复或多或少会起作用。即应用程序重新打开正确的表格视图。然而,表格视图总是滚动到顶部,即使它之前滚动到另一个位置。

这是UIDataSourceModelAssociation我的表视图控制器中方法的实现。那里没有什么特别的事情(该NdlFriend::accountUid属性返回给定 NdlFriend 记录的唯一标识符字符串):

#pragma mark - UIDataSourceModelAssociation
- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)idx inView:(UIView *)view
{
    NSString* identifier = nil;
    NSArray* content = self.contentArray;

    // Sometimes idx might be nil...
    if(idx && idx.row<content.count)
    {
        NdlFriend* friend = content[idx.row];
        identifier=friend.accountUid;
    }
    return identifier;
}

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view
{
    NSIndexPath * indexPath=nil;
    NSArray* content = self.contentArray;
    NSInteger count = content.count;
    for(NSInteger i=0;i<count;i++)
    {
        NdlFriend* friend = content[i];
        if([identifier isEqualToString:friend.accountUid])
        {
            indexPath = [NSIndexPath indexPathForRow:i inSection:0];
            break;
        }
    }
    return indexPath;
}

我在这两种方法中都设置了断点。

为了测试这些方法,我打开了表格视图并向下滚动了一点。然后,当按下主页按钮时:

  • modelIdentifierForElementAtIndexPath:inView:被调用一次,带有最顶部可见行的索引路径。该方法返回此行的正确 uid。

到目前为止,一切都很好。

然后我停止并重新启动应用程序。这是发生的事情(我对第一个命中断点特别困惑):

  • modelIdentifierForElementAtIndexPath:inView:被调用,nil作为索引路径(视图参数包含表视图的正确指针)。
  • indexPathForElementWithModelIdentifier:inView:使用有效的标识符字符串调用(并且该方法返回有效的索引路径)。
  • indexPathForElementWithModelIdentifier:inView:再次被调用(使用相同的标识符字符串)。
  • 表格视图已刷新,但滚动到最顶部。

有人知道,为什么滚动位置的恢复失败?modelIdentifierForElementAtIndexPath:inView:with nilas indexPath的调用是否与它有关(或者这是正常行为)。

4

4 回答 4

1

iOS 6 中有一个关于导航控制器中表视图状态恢复的错误。

你可以在这里看到开放的雷达:rdar://13438788

如您所见,它是重复的,因此 Apple 意识到了这一点。

此外,请参阅下一个链接,发布开放雷达的人也发表了这篇博文,其中包含 Apple 工程师告诉他的建议解决方法。

它使状态保存/恢复对我来说不是一个令人愉快的功能,但请记住,这是为您的用户准备的!所以无论如何你都应该做解决方法。

请注意,有 2 种解决方法,一种用于恢复表视图的视图信息(例如滚动偏移),另一种用于在实现时使用的解决方法UIDataSourceModelAssociation是您的情况。

http://useyourloaf.com/blog/2013/04/07/bug-table-view-state-not-restored-when-embedded-in-navigation-controller.html

于 2013-05-05T19:55:44.877 回答
0

我同意 Aky 的观点,这可能确实是 iOS 6 中的一个错误。请参阅我对相关问题的回答:https ://stackoverflow.com/a/14567551/322548

于 2013-01-28T17:21:32.043 回答
0

确保您没有对数据执行异步提取。如果您从 viewDidLoad 获取数据,请确保使用 [myManagedObjectContext performBlockAndWait:^{}] 调用而不是 [myManagedObjectContext performBlock:^{}]。

当调用 indexPathForElementWithModelIdentifier 时,您可能有一个竞争条件 self.contentArray 为空。

于 2014-12-06T21:30:45.270 回答
0

我认为您在重置表格视图的滚动位置时遇到的问题与 UIDataSourceModelAssociation 方法无关。

我相信嵌入在导航控制器中的表格视图控制器存在错误,导致它在恢复后重置其滚动位置。据我了解,如果您的表格视图中的单元格没有重新排序,则您不需要实现 UIDataSourceModelAssociation 方法,并且您应该“免费”获得滚动位置(即,只要您选择了状态保存并设置修复体 ID)。我不能从文档中明确地确认这一点,除了指出 UITableView 来自 UIScrollView,它保存了它的滚动位置。我已经测试过,如果将表视图控制器设置为根控制器,或者将表视图控制器嵌入标签栏控制器,则滚动位置恢复。

我已经提交了一个错误报告,如果你还没有,你也应该这样做。

于 2012-12-25T08:12:13.473 回答