0

NSFetchedResultsController によって管理されるテーブル ビューがあります。ただし、検索または作成操作に問題があります。ユーザーがテーブル ビューの一番下に到達すると、別のコンテンツのバッチをサーバーに照会しています。ローカル キャッシュに存在しない場合は、作成して保存します。ただし、存在する場合は、そのデータを取得した結果コントローラーに追加して表示したいと考えています。その部分がよくわかりません。

これまでのところ、私がやっていることは次のとおりです。

  1. データベースからの最新の 100 件の結果に対するクエリを初期化したときの NSFetchedRequestController ( を使用setFetchLimit:)。1000 行あっても、最初は 100 行だけアクセスできるようにしたいです。
  2. サーバーから返された値の配列を NSOperation に渡して処理します。
  3. 操作では、操作する新しい管理対象オブジェクト コンテキストを作成します。
  4. この操作では、配列を繰り返し処理し、フェッチ リクエストを実行して、オブジェクトが存在するかどうかを (サーバー ID に基づいて) 確認します。
  5. オブジェクトが存在しない場合は、オブジェクトを作成し、操作の管理対象オブジェクト コンテキストに挿入します。
  6. 反復が完了したら、マネージド オブジェクト コンテキストを保存します。これにより、メイン スレッドでマージ通知がトリガーされます。

マージ中に、手順 4 で新しく作成されたオブジェクトがテーブルに挿入されますが、既に存在し、フェッチされたばかりのオブジェクトは挿入されません。これが私の NSOperation からの関連コードです

for (NSDictionary *resultsDict in self.results)
{
    NSNumber *dbID = [NSNumber numberWithLong:[[resultsDict valueForKey:@"id"] longValue]];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[NSEntityDescription entityForName:kResultEntityName inManagedObjectContext:moc]];
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat: @"(dbID == %@)", dbID]];

    NSError *error = nil;

    NSManagedObject *newObject = nil;
    // Query the data store to see if the object exists
    newObject = [[moc executeFetchRequest:fetchRequest error:&error] lastObject];
    [fetchRequest release];

    // If it doesn't exist, create it.
    if ((tweet == nil))
    {
        // Create the NSManagedObject and insert it into the MOC.  
    }
}

メインスレッドに渡したいのは、新しく作成されたオブジェクトと、ループが繰り返されるたびにフェッチ要求でフェッチされた可能性のある既存のオブジェクトです。

それは私が見逃している単純なものであり、正しい方向に微調整を使用できるように感じます.

4

3 に答える 3

1

この時点で、以前に Core Data ストアにローカルにキャッシュされていなかったオブジェクトが表示されますが、以前に存在していたオブジェクトは表示されません。

これについて少し説明していただけますか?以前に存在したものとはどういう意味かわかりません。テーブルのフィルターに一致しなかったオブジェクトが検索後に一致するのでしょうか、それとも以前のオブジェクトがテーブルから消えると言っているのですか?

また、のデリゲート メソッドをどのように実装していNSFetchedResultsControllerますか? 単純なテーブルのリロードを行っていますか、それとも行を挿入/移動していますか?

アップデート

これを行うにはいくつかの方法がありますが、ユーザー側でいくつかの実験が必要になります。最初に、フェッチされたオブジェクトに「触れる」というアイデアで遊んでみました。おそらく、「lastAccessed」日付または何かを更新して、これらのオブジェクトがマージで「更新済み」として検出されるようにします。それが一番楽な道だと思います。

それをむき出しにして、別のオプションは、これらのオブジェクトの通知をメインスレッドにブロードキャストして (NSManagedObjectIDスレッド境界を越えてキャリアとして使用して)、手動で更新できるようにすることです。しかし、それは理想的とは言えません。

于 2010-04-07T16:12:39.523 に答える
0

ちょっとジャスティン、あなたfetchLimitがこれを引き起こしているのでしょうか?

NSFetchedRequestControllerデータベースからの最新の 100 件の結果に対する when initialized クエリ ( を使用 ) setFetchLimit:。1000 行あっても、最初は 100 行だけアクセスできるようにしたいです。

NSFetchedResultsController挿入およびマージする管理対象オブジェクトの数に関係なく、結果は 100 件に制限されます。

ソートをオンにしていますか?その場合、挿入された管理対象オブジェクトの一部が表示されている可能性があります。これは、結果の順序によって既存の 100 個の一部が置き換えられるためです。

私は結果の「ページ」をフェッチすることで同じ問題を経験し、フェッチに下限制約を適用し (で sorted 属性を使用NSComparisonPredicate)、最新の「ページ」の最後の項目でそれを調整しました結果。

fetchLimit アプローチも試してみましたが、それもうまくいきました。を削除して再構築する必要はありませんNSFetchedResultsController。fetchRequest の fetchLimit を調整するだけです。

tableMaxItems += 100;
[myFRC.fetchRequest setFetchLimit:tableMaxItems];
于 2010-04-09T04:33:02.697 に答える
0

これが私がこれを修正した方法です。NSOperationmyの MOCからの変更をマージする前に、に格納されている値を反復処理し、NSUpdatedObjectsKeyそれらに willAccessValueForKey を適用します。それらをキーにするために、上記のマーカスのアドバイスを受けて、オブジェクトが永続ストアに既に存在する場合にNSUpdatedObjects現在の日付に設定する lastAccessed プロパティを追加しました。NSOperation

- (void)mergeChanges:(NSNotification *)notification
{
  NSAssert([NSThread mainThread], @"Not on the main thread");  
  NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];

  for (NSManagedObject *object in updatedObjects)
  {
    [[managedObjectContext objectWithID:[object objectID]] willAccessValueForKey:nil];
  }

  [managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
于 2010-04-12T15:09:13.247 に答える