2013-01-06 68 views
0

我一直在使用RSS閱讀器,使用核心數據進行緩存。像很多人一樣,我想避免重複輸入,這導致我出現了this的問題,並且還有this one。 但是,我還想要另一件事,我還希望讓用戶能夠刪除文章,並避免在刷新Feed時再次添加已刪除的文章,即如果刪除的文章仍然存在於Feed中。所以,我現在的解決方案是,在託管對象上下文中維護另一個實體,並使用唯一標識符(我如何識別Feed中的每個項目)刪除文章,我只是將要刪除的文章的標識符添加到該實體,並檢查它。核心數據,重複和刪除的RSS條目

現在,我寫了一段代碼來完成上述所有操作。每次在解析過程中解析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中嘗試過)。所以,我想我的問題是,是否有更有效的方式來做我想在這裏做的事情,希望不會凍結UI? 也許更好的處理被刪除的文章?

回答

3

我的第一個建議是通過爲文章實體添加一個「itemDeleted」屬性來處理刪除的文章。然後,只有一個要插入新項目時要檢查的對象列表。

提示:不要叫「刪除」該屬性isDeleted是一個內置的NSManagedObject屬性,所以很可能會導致名稱衝突。)

下一個建議是救所有項目已導入後才管理對象上下文,而不是之後的每個每個項目(編輯:又見咖啡因的答案,這是我在寫這一點的同時公佈。)

最後,搜索每個新項目所有文章的清單分開ly是一種不能很好地擴展的模式。 Implementing Find-or-Create Efficiently的「核心數據編程指南」中的描述,可能是更好的一種模式:

  • 爲將要插入的項目列表,執行取它們已經出現在這個名單上的所有項目獲取請求數據庫
  • 並行遍歷新項目列表和獲取列表以找出哪些項目是新的並且必須被插入。
+0

+1好的建議使用*查找或創建模式*。但是我沒有看到後臺線程@SamJ的上下文每個線程都需要創建自己的上下文。你可以通過它們的'NSManagedObjectID'在線程之間共享對象。 –

+0

@flexaddicted我實際上並沒有在後臺線程中對託管對象上下文做任何事情。我在後臺線程中做的唯一的事情是檢查已經存在的數組(以前從主線程的託管對象上下文中獲取)用於退出和刪除的文章,並創建一個新條目,將其保存到主要的託管對象上下文線。後臺線程的目的就是避免凍結UI。 –

+0

@SamJ .: flexaddicted是對的:你可以在後臺線程中調用'insertNewObjectForEntityForName'。但是所有的核心數據操作都必須在與上下文關聯的線程/隊列上完成。 –

1

由於將所有對象寫出到磁盤需要幾秒鐘,UI凍結很可能是由[self.managedObjectContext save:&error]造成的。 iOS 5+的一個很好的解決方案是嵌套上下文。請參閱此博客文章以獲取更多詳細信息http://www.cocoanetics.com/2012/07/multi-context-coredata/,特別是最後的異步保存部分。

+0

只是關於嵌套上下文的警告。我浪費了很多時間來解決他們的許多錯誤。這篇文章總結了很多問題,我也有其他問題。我認爲他們還沒有準備好。 http://wbyoung.tumblr.com/post/27851725562/core-data-growing-pains –