Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIKit state preservation not restoring scroll offset

I have an app that is using UIKit state preservation in iOS 6. I am able to save/restore the state of the view controllers, ie which tab is selected and navigation controller hierarchy, however I cannot get my table view to restore it's offset. I have a restoration identifier in my storyboard for the view as well as the view controller and the view controller (the table's data source) implements UIDataSourceModelAssociation as follows:

- (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: is getting called when the app goes into the background, however modelIdentifierForElementAtIndexPath:inView: never gets called.

like image 590
David Beck Avatar asked Nov 28 '12 19:11

David Beck


1 Answers

This isn't a real answer to your question, but I've not been able to get a table view restore its contentOffset, either.

I guess this is a bug in iOS 6, because the documentation clearly states that a UITableView restores its contentOffset, when 1) it has a restorationIdentifier 2) the view controller the view belongs to has a restorationIdentifier and 3) the data source conforms to the UIDataSourceModelAssociation protocol.

You can restore the contentOffset and the selected item manually in your view controller, though:

- (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];
        }
    }
}

I have no idea why UITableView doesn't do that automatically, even though the documentation says it does. If someone knows the answer, please comment.

like image 168
Fabian Kreiser Avatar answered Sep 17 '22 15:09

Fabian Kreiser