2013-04-26 53 views
0

這是來自RW教程的SyncEngine。我需要幫助瞭解如何只從Web獲取UPDATE記錄並將其處理到Core Data中。此代碼如何僅將更新用於核心數據?

- (void)processJSONDataRecordsIntoCoreData { 
    NSManagedObjectContext *managedObjectContext = [[SDCoreDataController sharedInstance] backgroundManagedObjectContext]; 
    // Iterate over all registered classes --- CHECK! 
    for (NSString *className in self.registeredClassesToSync) { 
     if (![self initialSyncComplete]) { 
      NSDictionary *JSONDictionary = [self JSONDictionaryForClassWithName:className]; 
      NSArray *records = [JSONDictionary objectForKey:@"results"]; 
      for (NSDictionary *record in records) { 
       [self newManagedObjectWithClassName:className forRecord:record]; 
      } 
     } else { 
      NSArray *downloadedRecords = [self JSONDataRecordsForClass:className sortedByKey:@"objectId"]; 
      if ([downloadedRecords lastObject]) { 
       NSArray *storedRecords = [self managedObjectsForClass:className sortedByKey:@"objectId" usingArrayOfIds:[downloadedRecords valueForKey:@"objectId"] inArrayOfIds:YES]; 
       int currentIndex = 0; 
       //if dl count is < current index, there is an updated object dl from the web 
       for (NSDictionary *record in downloadedRecords) { 
        NSManagedObject *storedManagedObject = nil; 
        //Quick check to see if they indeed match, if they do, update the stored object with remote service objects 
        if ([storedRecords count] > currentIndex) { 
         storedManagedObject = [storedRecords objectAtIndex:currentIndex]; 
        } 
        //Othwerwise its a new object and you need to create a new NSManagedObject to represent it in CDdb 
        if ([[storedManagedObject valueForKey:@"objectId"] isEqualToString:[record valueForKey:@"objectId"]]) { 
         [self updateManagedObject:[storedRecords objectAtIndex:currentIndex] withRecord:record]; 
        } else { 
         [self newManagedObjectWithClassName:className forRecord:record]; 
        } 
        currentIndex++; 
       } 
      } 
     } 
     // After all NSMO are created in your context, save it! 
     [managedObjectContext performBlockAndWait:^{ 
      NSError *error = nil; 
      if (![managedObjectContext save:&error]) { 
       NSLog(@"Unable to save context for class %@", className); 
      } 
     }]; 
     // Cleanup time 
     [self deleteJSONDataRecordsForClassWithName:className]; 
     [self executeSyncCompletedOperations]; 
    } 

    [self downloadDataForRegisteredObjects:NO]; 
} 

據我瞭解,在第一或初始同步,它提取JSONDictionaryForClassWithName從磁盤讀取下載的數據,並創建一個newManagedObjectWithClassName。

我的困惑是在更新else塊中。 downloadedRecords從JSONDataRecordsForClass填充,它只是簡單地調用JSONDictionaryForClassWithName。然後檢查該數組中是否至少有一個對象。如果它這樣做:

NSArray *storedRecords = [self managedObjectsForClass:className sortedByKey:@"objectId" usingArrayOfIds:[downloadedRecords valueForKey:@"objectId"] inArrayOfIds:YES]; 

此獲取所有managedObjectsForClass:sortedByKey其低於:

- (NSArray *)managedObjectsForClass:(NSString *)className sortedByKey:(NSString *)key usingArrayOfIds:(NSArray *)idArray inArrayOfIds:(BOOL)inIds { 
    __block NSArray *results = nil; 
    NSManagedObjectContext *managedObjectContext = [[SDCoreDataController sharedInstance] backgroundManagedObjectContext]; 
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:className]; 
    NSPredicate *predicate; 
    if (inIds) { 
     predicate = [NSPredicate predicateWithFormat:@"objectId IN %@", idArray]; 
    } else { 
     predicate = [NSPredicate predicateWithFormat:@"NOT (objectId IN %@)", idArray]; 
    } 

    [fetchRequest setPredicate:predicate]; 
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject: 
             [NSSortDescriptor sortDescriptorWithKey:@"objectId" ascending:YES]]]; 
    [managedObjectContext performBlockAndWait:^{ 
     NSError *error = nil; 
     results = [managedObjectContext executeFetchRequest:fetchRequest error:&error]; 
    }]; 

    return results; 
} 

,其比較所述[storedRecords計數]下位> CURRENTINDEX是混亂的。有人可以解釋這個嗎?我認爲我的困惑在於managedObjectsForClass方法對inArrayOfId的useArraysOfIds &做了什麼。

我認爲在某些時候,它會從下載的記錄中獲取updatedAt字段,並將其與CoreData獲取記錄的updatedAt字段進行比較。

回答

0

該函數正在處理存儲的JSON。實際的遠程讀取和更新檢查發生在downloadDataForRegisteredObjectsmostRecentUpdatedAtDateForEntityWithName

[storedRecords count] > currentIndex有點瘋狂。儘管爲了保護原來的程序員,編寫任何體面的syncengine都會很快讓你去googoo。基本上他需要確定哪些記錄存在,哪些是新的,並相應地更新本地數據存儲,就這些了。


我又看了一遍,這段代碼實際上是非常可怕的。只有在本地和遠程都有相同的記錄時,它纔會起作用。或者,如果新對象有一個objectId,它在本地存儲的最後一個對象之後進行排序。 Parse objectId的情況並非如此。

如果您僅使用一個設備進行測試,則可以使用該功能,因爲新對象在被推送到服務器之前將在本地插入。因此,您將始終擁有相同數量的記錄。如果以其他方式插入其他記錄,則此代碼會執行奇怪的操作。

+0

這正是我想了解它爲什麼有效的問題,「確定哪些記錄存在,哪些是新的」。相信我,我一直在努力理解這個代碼,我很欣賞複雜性! :)。你能否解釋現有的和新的如何工作? – marciokoko 2013-04-27 03:31:06

相關問題