我有一个在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:
永远不会被调用。
答案 0 :(得分:3)
这不是你问题的真正答案,但我也无法让表格视图恢复其contentOffset。
我想这是iOS 6中的一个错误,因为文档明确指出UITableView
恢复其contentOffset,1)它有一个restorationIdentifier
2)视图所属的视图控制器具有a 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
不会自动执行此操作,即使文档说它确实如此。如果有人知道答案,请发表评论。
答案 1 :(得分:3)
我发现如果UITableView 还设置了restoreIdentifier,这可以正常工作。
但是如果UITableViewController在UINavigationController中,它就不起作用。这已经报告给Apple,问题ID:13536778。iOS 6.0和6.1.3上似乎都出现了这个问题。
答案 2 :(得分: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];
}
答案 3 :(得分:0)
有关如何实现此操作的信息,请参阅Apple的州立恢复样本。魔术修复发生在decodeRestorableStateWithCoder
方法中,并调用了reloadData
:
// 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
中,这不是一个好主意,因为它被多次调用(至少两次)以查找可见对象和选定对象的各种索引路径。