Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange calls to modelIdentifierForElementAtIndexPath:inView: (UIDataSourceModelAssociation)

Tags:

ios

ios6

I'm currently implementing automatic state preservation/restoration in an iOS6-only app.

For a restoration of a table view, I added the UIDataSourceModelAssociation protocol to my table view controllers and implemented

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

and

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

When pressing the home button, the state preservation methods, including modelIdentifierForElementAtIndexPath:iView:, are getting called as expected and return valid identifier strings for the given index paths.

When killing the app and relaunching it, state restoration works more or less. I.e. the app re-opens the correct table view. However, the table view is always scrolled to the top, even when it was scrolled to another position before.

Here's the implementation of the UIDataSourceModelAssociation methods in my table view controller. Nothing fancy going on in there (the NdlFriend::accountUidproperty returns a unique identifier string for a given NdlFriend record):

#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;
}

I set break points in both methods.

To test the methods, I opened the table view and scrolled down a little bit. Then, when pressing the home button:

  • modelIdentifierForElementAtIndexPath:inView: gets called once, with the index path of the top most visible row. The method returns the correct uid for this row.

So far so good.

Then I stop and relaunch the app. Here's what happens (I'm especially puzzled by the first hit break point):

  • modelIdentifierForElementAtIndexPath:inView: gets called, with nil as index path (the view argument contains the correct pointer of the table view).
  • indexPathForElementWithModelIdentifier:inView: gets called with a valid identifier string (and a valid index path is returned by the method).
  • indexPathForElementWithModelIdentifier:inView: gets called again (with the same identifier string).
  • The table view is refreshed, but scrolled to the very top.

Does someone know, why the restoration of the scroll position fails? Does maybe the call of modelIdentifierForElementAtIndexPath:inView: with nil as indexPath has something to do with it (or is this normal behavior).

like image 811
Zaggo Avatar asked Nov 06 '12 15:11

Zaggo


1 Answers

There is a bug in iOS 6 regarding state restoration of Table Views in Navigation Controllers.

You can see the open radar here: rdar://13438788

As you can see, it's a duplicate, so Apple are aware of this.

Also, see this next link, the guy who posted that open radar also did this blog post, it has the suggested workarounds that the Apple Engineers told him.

It makes the state preservation/restoration for me not such an enjoyable feature to implement, although remember, this is for your users ! So you should just do the workaround anyway.

Note there are 2 workarounds, one for the table view's view information to restore (scroll offset for example), and another workaround for the use when implementing UIDataSourceModelAssociation which is your case.

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

like image 56
Daniel Avatar answered Sep 22 '22 22:09

Daniel