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:一番上に表示されている行のインデックス パスを使用して、1 回呼び出されます。このメソッドは、この行の正しい uid を返します。

ここまでは順調ですね。

次に、アプリを停止して再起動します。何が起こるかは次のとおりです (特に、最初のヒット ブレーク ポイントに困惑しています)。

  • modelIdentifierForElementAtIndexPath:inView:インデックス パスとして呼び出さnilれます (ビュー引数には、テーブル ビューの正しいポインターが含まれます)。
  • indexPathForElementWithModelIdentifier:inView:有効な識別子文字列で呼び出されます (メソッドによって有効なインデックス パスが返されます)。
  • indexPathForElementWithModelIdentifier:inView:(同じ識別子文字列で) 再度呼び出されます。
  • テーブル ビューは更新されますが、一番上までスクロールされます。

スクロール位置の復元が失敗する理由を誰かが知っていますか? modelIdentifierForElementAtIndexPath:inView:with nilindexPath の呼び出しが何か関係があるのか​​もしれません (または、これは通常の動作です) 。

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

テーブル ビューのスクロール位置のリセットに関する問題は、UIDataSourceModelAssociation メソッドに関係しているとは思いません。

ナビゲーションコントローラーに埋め込まれたテーブルビューコントローラーにバグがあり、復元後にスクロール位置がリセットされると思います。私が理解しているように、テーブルビューのセルが並べ替えられない場合、UIDataSourceModelAssociation メソッドを実装する必要はなく、スクロール位置を「無料で」取得する必要があります (つまり、状態の保存を選択している限り)。修復物 ID を設定します)。UITableView がスクロール位置を保存する UIScrollView から派生していることを指摘することを除いて、ドキュメントからこれを明示的に確認することはできません。テーブル ビュー コントローラーをルート コントローラーに設定するか、テーブル ビュー コントローラーをタブ バー コントローラーに埋め込むと、スクロール位置復元されることをテストしました。

バグ レポートを提出しました。まだ提出していない場合は、提出する必要があります。

于 2012-12-25T08:12:13.473 に答える
0

データに対して非同期フェッチを実行していないことを確認してください。viewDidLoad からデータを取得する場合は、[myManagedObjectContext performBlock:^{}] の代わりに [myManagedObjectContext performBlockAndWait:^{}] 呼び出しを使用してください。

indexPathForElementWithModelIdentifier が呼び出されたときに、self.contentArray が空であるという競合状態が発生している可能性があります。

于 2014-12-06T21:30:45.270 に答える
0

私はAkyに同意します。これは確かにiOS 6のバグかもしれません。関連する質問に対する私の回答を参照してください: https://stackoverflow.com/a/14567551/322548

于 2013-01-28T17:21:32.043 に答える