0

我有一個NSManagedObjectContext與主線程(mainContext)相關聯,我獲取所有在整個應用程序中顯示的NSManagedObject從異步Web服務響應更新託管對象的最佳方法?

用戶不編輯這些對象,但我從Web服務獲取更新。我定期對這些服務執行異步調用,並且「告訴」我需要刪除哪些管理對象(如果有),哪些必須用新信息更新(如果有),以及是否需要插入新的對象。

因此,我需要首先獲取所有服務的響應,然後檢查我必須對我的mainContext中已有的管理對象所做的更改。而且我還需要執行更新以避免阻止UI。

我考慮2種方式來管理這樣的情景:

  1. 要使用符合自身核心數據的專用隊列完全分離privateContext堆插入那裏所有我從服務中獲得的對象。然後以某種方式(如何?)與mainContext中的對象進行比較,然後刪除/修改/插入mainContext中的對象。
  2. 在專用隊列中使用privateContext,但是作爲mainContext的子代。然後,我需要將子對象傳遞給其父對象mainContext中的對象(這可能嗎?怎麼做?),同時在這個子對象中插入從服務獲得的對象,然後比較和執行更改。

什麼樣的方法是最好的還是最合適的?或者,也許它應該是我沒有想過的另一個?

預先感謝

編輯:這會是另一種可能的方式?:

  • 僅使用mainContext,正如我解析的響應該服務,而不是創建新的對象只是作出mainContext逐一...
  • EDIT 2的變化:另一種可能性?:

    1. 只使用privateContext,獲取服務響應並創建新對象。然後,也可以使用此privateContext獲取所有已存在的對象(並且與mainContext中的對象相同)。在這個privateContext中比較兩組對象(最近從服務和提取創建的對象)進行更改,保存此上下文,清除mainContext並重新獲取mainContext中的所有對象。
    +0

    您的對象是否有任何ID屬性? – kirander

    +0

    @kirander是的,他們有 – AppsDev

    +0

    在父上下文中使用私有上下文。通過從服務器響應中獲取的ID從存儲中獲取所需的對象。根據情況更新,刪除或創建新的。 – kirander

    回答

    0

    我不確定這是一個完整的答案,但我正在研究一個類似的情況。我所採用的實現路徑是使用子對象(遍佈整個地方) - 或者根據需要更像臨時子上下文。

    然而,我應該提到的第一件事是確保使用CoreData調試功能構建到XCOde中。我做了第二次運行計劃有

    -com.apple.CoreData.ConcurrencyDebug 1

    enter image description here

    在應用程序初始化我有我的正常NSManagedObjectContext - 這是各地傳遞給我的後臺網絡線程。

    NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
        [child setParentContext:parentObjectContext]; 
    

    然後,每當我需要從父傳的東西孩子,我最終會做:

    [child objectWithID:(object-in-parent-context)] 
    

    或者我最終會做

    __block AHRS_RPYL * ret; 
    
    [[self getChildContext] performBlockAndWait:^{ 
    
        ret = [NSEntityDescription insertNewObjectForEntityForName:@"RPYL" inManagedObjectContext:[self getChildContext]]; 
    
    // ... lots of code 
    }]; 
    

    我不能說我真的「愛「這種方法,而且我暫時堅持它,但它似乎工作得很好。

    我的大部分視圖控制器之間我有一個

    @synthesize managedObjectContext; 
    

    在我prepareForSegue方法

    // Pass on managedObjectContext 
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    
        // dispatch_async(dispatch_get_main_queue(), ^{ 
        // If the destination VC is able to take teh setManagedObjectContext method the current objectContext will be passed along. 
        if ([segue.destinationViewController respondsToSelector:@selector(setManagedObjectContext:)]) { 
         [segue.destinationViewController performSelector:@selector(setManagedObjectContext:) 
                   withObject:self.managedObjectContext]; 
    
        } else { 
    
         NSLog(@"Segue to controller [%@] that does not support passing managedObjectContext", [segue destinationViewController]); 
        } 
        // }); 
    } 
    

    摘要

    • 我和你的第二個選擇的選項,它的工作雖然在我誠實的意見中感覺有點笨拙,但是可以做到。事實是,我們正在考慮切換到Realm而不是CoreData,因爲無論您如何看待它,CoreData都不是最易於使用的選項。

    UDPATES

    節省代碼

    其實我救孩子上下文每50個消息,並於母公司每250它看起來像(沒有觸及在這個年齡段代碼)。我不能保證這是做最好的正確方法,但它確實有效,並且確保光盤訪問最小化。我收到了很多消息,比如20+秒,所以我想要做這個堆棧類型。你可能不在乎

    (self.getChild())返回子上下文 - 它的舊代碼我離開這裏。

    if (msgCount % 50 == 0) { 
           // Child Save! 
    
           //     NSLog(@"Saving SDatas"); 
           __block NSManagedObjectContext *currentChild = [self getChildContext]; 
           [self incChildContext]; 
    
           // Parent-Child save methodology 
           [currentChild performBlock:^{ 
            NSError *error; 
            if (![currentChild save:&error]) { 
             NSLog(@"\n error => %@ \n", [error localizedDescription]); 
             NSLog(@" error => %@ ", [error userInfo]); 
             [NSException raise:@"Database Write Error" format:@"%@ %@", [error localizedDescription], [error userInfo]]; 
    
             //       abort(); 
            } 
    
            if (msgCount % 250 < 5) { 
    
             [parentObjectContext performBlock:^{ 
              NSError *error; 
              if (![parentObjectContext save:&error]) { 
               NSLog(@"\n error => %@ \n", [error localizedDescription]); 
               NSLog(@" error => %@ ", [error userInfo]); 
               [NSException raise:@"Database Write Error" format:@"%@ %@", [error localizedDescription], [error userInfo]]; 
    
               //         abort(); 
    
    
              } 
             }]; 
            } 
    
            [currentChild reset]; 
           }]; 
    
    
          } 
    

    刪除

    [childContext performBlock:^{ 
    
    // LOTS OF CODE 
    // to build a query set of the records we want to kill 
    // End lots of code 
    [childContext deleteObject:msg]; 
    
    
         if (i % modFactor == 0) { 
          self.percentDone = i/totalRecords; 
    
          NSLog(@"%.1f Saving ...", self.percentDone * 100); 
    
    
          NSError *error; 
          if (![childContext save:&error]) { 
           NSLog(@"\n error => %@ \n", [error localizedDescription]); 
           NSLog(@" error => %@ ", [error userInfo]); 
           [NSException raise:@"Database Write Error" format:@"%@ %@", [error localizedDescription], [error userInfo]]; 
    
           //     abort(); 
          } 
    
          [parentContext performBlock:^{ 
           NSError *errrror; 
           if (![parentContext save:&errrror]) { 
            NSLog(@"\n error => %@ \n", [error localizedDescription]); 
            NSLog(@" error => %@ ", [error userInfo]); 
            [NSException raise:@"Database Write Error" format:@"%@ %@", [error localizedDescription], [error userInfo]]; 
    
            //      abort(); 
           } 
          }]; 
         } 
    
    }]; 
    

    ...

    再次 - 就像我之前說這可能不是做事情的最好方法,但我有一個父/子堆棧和它工作。這是我編寫的第一批iOS應用程序之一,爲了再次完成它,我打了核心數據並使用其他內容。

    我們有一個非常高的更新率,所以當我們使用一個單一的堆棧時,它使得用戶界面非常緩慢。遷移到父母/孩子的速度很慢 - 我再次這樣做,我認爲它會變得更順暢,因爲我會寫很多幫助函數來處理這些問題(或者只是使用swift)。

    祝你好運。

    +0

    感謝您的解釋。我想應該在子上下文的「performBlockAndWait:」內調用[[child objectWithID:(object-in-parent-context)]],對吧? – AppsDev

    +0

    關於這種方法:當您從子上下文中刪除從其父級傳遞的對象時,該子對象在保存時也會從父級上刪除?在兒童上下文中插入的相同問題。我需要在執行更新時進行刪除和插入,而不僅僅是更改現有對象...再次感謝 – AppsDev

    +0

    我將更新我的答案... – Jeef

    相關問題