0

キャッシュにコア データを使用して、RSS リーダーに取り組んできました。多くの人と同じように、重複したエントリを避けたかったため、この質問とこの質問に至りました。しかし、もう 1 つ、ユーザーが記事を削除できる機能を提供し、フィードを更新するときに、削除された記事がまだフィードに存在する場合に、削除された記事を再度追加しないようにしたいと考えていました。したがって、現在の私の解決策は、削除された記事の一意の識別子 (フィード内の各アイテムを識別する方法) を持つ別のエンティティを管理オブジェクト コンテキストに維持することです。削除されている記事の識別子をそのエンティティに追加するだけです。 、それに対してチェックします。

ここで、上記のすべてを達成するために私が書いたコードを示します。このコードは、解析プロセス中にフィード内の新しいアイテムが解析されるたびに実行されます。

    dispatch_queue_t checkQueue = dispatch_queue_create("com.feedreader.backgroundchecking", NULL);

    dispatch_async(checkQueue,^{
        NSMutableArray *mutablesortedArticles = [NSMutableArray arrayWithArray:self.feeds.sortedArticles];

        if (!mutablesortedArticles) {
            // Handle the error.
        }

        if ([[mutablesortedArticles valueForKey:@"identifier"]
             containsObject:article.identifier]) {
            NSLog(@"This article already exists");
            return;
        }else {
            NSMutableArray *mutabledeletedArticles = [NSArray arrayWithArray:self.alldeletedArticles];

            if (!mutabledeletedArticles) {
                // Handle the error.
            }

            if ([mutabledeletedArticles valueForKey:@"identifier"]
                 containsObject:article.identifier]) {
                NSLog(@"This article has been deleted");
                return;
            }else {
                Article *newArticle = [NSEntityDescription insertNewObjectForEntityForName:@"Article" inManagedObjectContext:self.managedObjectContext];

                newArticle.title = article.title;
                newArticle.date = article.date;
                newArticle.link = article.link;
                newArticle.summary = article.summary;
                newArticle.image = article.image;
                newArticle.identifier = article.identifier;
                newArticle.updated = article.updated;
                newArticle.content = article.content;
                newArticle.feed = self.feed;

                dispatch_async(dispatch_get_main_queue(),^{
                    NSError *error = nil;
                    [self.managedObjectContext save:&error];
                    if (error) {
                        NSLog(@"%@", error);
                    }
                });
            }
        }
    });

self.feeds.sortedArticles と self.alldeletedArticles の両方が、解析が開始される前に管理オブジェクト コンテキストから取得されます。

私の問題は、このコードが実行されているときに始まり、UI が 1 ~ 2 秒間フリーズします (管理オブジェクト コンテキストに 500 を少し超える記事があるフィードで試しました)。だから、私の質問は、私がここでやろうとしていることを行うためのより効率的な方法、うまくいけばUIをフリーズさせない方法があるということだと思いますか? おそらく、削除された記事を処理するためのより良い方法でしょうか?

4

2 に答える 2

3

私の最初の提案は、 Articleエンティティに「itemDeleted」プロパティを追加して、削除された記事を処理することです。次に、新しいアイテムを挿入するときにチェックするオブジェクトのリストは 1 つだけです。

(ヒント:その属性を「deleted」と呼ばないでください。isDeletedは の組み込みプロパティでNSManagedObjectあるため、名前の競合が発生する可能性があります。)

次の提案は、各アイテムの後ではなく、すべてのアイテムがインポートされた後にのみ管理対象オブジェクト コンテキストを保存することです (編集:これを書いている間に投稿された Caffeine の回答も参照してください)。

最後に、すべての記事のリスト内の新しい項目を個別に検索するのは、うまくスケーリングできないパターンです。「Core Data Programming Guide」の Find-or-Create Efficiently の実装では、より適切なパターンが説明されています。

  • 挿入されるアイテムのリストについては、データベースに既に存在するこのリストのすべてのアイテムをフェッチするフェッチ要求を実行します。
  • 新しいアイテムのリストとフェッチされたリストの両方を並行してトラバースし、どのアイテムが本当に新しく、挿入する必要があるかを見つけます。
于 2013-01-06T10:58:47.750 に答える
1

[self.managedObjectContext save:&error]すべてのオブジェクトをディスクに書き出すのに数秒かかるため、UI のフリーズが原因である可能性があります。iOS 5 以降でのこれに対する優れたソリューションは、ネストされたコンテキストです。詳細については、このブログ投稿http://www.cocoanetics.com/2012/07/multi-context-coredata/、特に最後の非同期保存セクションを参照してください。

于 2013-01-06T10:48:51.760 に答える