核心数据,重复和删除的RSS条目

时间:2013-01-06 09:58:09

标签: objective-c ios cocoa-touch core-data rss

我一直在使用RSS阅读器,使用核心数据进行缓存。像很多人一样,我想避免重复的条目,这导致我this提问,还有this one。 但是,还有我想要的另一件事,我还希望让用户能够删除文章,并避免在刷新Feed时再次添加已删除的文章,即如果已删除的文章仍存在于Feed中。因此,我目前的解决方案是,在我的托管对象上下文中维护另一个实体,其中包含已删除文章的唯一标识符(我如何识别Feed中的每个项目),我只是将要删除的文章的标识符添加到该实体,并检查它。

现在,这是我编写的一段代码,用于完成上述所有操作。每次在解析过程中解析Feed中的新项目时,都会运行此代码。

    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篇文章的Feed)。所以,我想我的问题是,有没有更有效的方法来做我想在这里做的事情,希望不会冻结用户界面? 也许是处理已删除文章的更好方法?

2 个答案:

答案 0 :(得分:3)

我的第一个建议是通过添加" itemDeleted"来处理已删除的文章。属性 Article 实体。然后,在插入新项目时,您只有一个要检查的对象列表。

提示:不要调用该属性"已删除"。isDeletedNSManagedObject的内置属性,因此可能会导致名称冲突。)

下一个建议是仅在导入所有项目之后保存托管对象上下文,而不是在每个项目之后保存(编辑:另请参阅咖啡因'回答,这是在我写这篇文章时发布的。)

最后,分别搜索所有文章列表中的每个新项目是一种不能很好地扩展的模式。 "核心数据编程指南"中的Implementing Find-or-Create Efficiently描述了一种可能更好的模式:

  • 要获取待插入项目的列表,请执行获取请求以获取此列表中已存在于数据库中的所有项目,
  • 并行地遍历新项目列表和获取列表,以找出哪些项目真的是新项目并且必须插入。

答案 1 :(得分:1)

UI冻结可能是由[self.managedObjectContext save:&error]引起的,因为将所有对象写入磁盘需要几秒钟。 iOS 5+中一个很好的解决方案是嵌套上下文。有关详细信息http://www.cocoanetics.com/2012/07/multi-context-coredata/,请参阅此博客文章,特别是最后的异步保存部分。