2013-05-14 5 views
0

Моя модель данных называется «Человек» и имеет 3 атрибуты «ID», «Имя» и «Фамилия»Ядро синхронизации данных с помощью JSON API

При импорте данных в формате JSON с помощью AFNetworking я хочу, чтобы иметь возможность чтобы проверить, существует ли объект уже или нет в Core Data с использованием «id» в качестве идентификатора. Если его нет, я бы хотел его создать, и если он есть, я хотел бы объединить элемент или обновить его.

прямо сейчас у меня есть метод, называемый duplicateCheck, который выглядит как:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id==%@", _person.id]; 
NSFetchRequest *fetch = [[NSFetchRequest alloc] init]; 
NSError *error = nil; 
[fetch setEntity:[NSEntityDescription entityForName:@"Person" inManagedObjectContext:self.managedObjectContext]]; 
[fetch setPredicate:predicate]; 
NSArray *items = [self.managedObjectContext executeFetchRequest:fetch error:&error]; 
for (NSManagedObject *object in items) { 
// Not sure how to check from here and insert or update 

// then save and call it during the API request? 
} 

У меня есть предикат установить, но я не уверен, куда идти отсюда. Перебирает ли каждый элемент правильный путь, или я об этом ошибаюсь?

+0

Вы можете использовать цикл, но ваш запрос должен возвращать только один объект, в противном случае у вас есть несогласованность данных и несколько объектов с одним и тем же идентификатором. –

+0

Бесстыдный плагин, но это может вам помочь. http://www.raywenderlich.com/15916/how-to-synchronize-core-data-with-a-web-service-part-1 –

ответ

0

Обычно можно было бы ожидать, что идентификатор будет уникальным. поэтому, если предикат возвращает 0 объектов, вы знаете, что этот объект является новым. Если возвращается 1, вы знаете, что этот объект уже существует и, возможно, вам нужно его обновить.

NSArray *items = [self.managedObjectContext executeFetchRequest:fetch error:&error]; 
if(items){ 
    if([items count] == 0){ 
     //the object is not present yet. create it. 
    } else if([items count] == 1) { 
     NSManageObject *obj = items[0]; 
     //there is exactly 1 object. change it properties if needed 
    } else { 
     //what to do if several objects have the same identifier??? 
    } 
} else { 
    //handle error from the error object 
} 
+0

Данные, которые поступают, имеют уникальный идентификатор для всех объектов «Человек». Поэтому мне не придется беспокоиться об объектах, имеющих одинаковый идентификатор. – cherbear

+0

Итак, каков ваш вопрос? – vikingosegundo

+0

Извините, что не добавили его. Если есть несколько объектов, которые необходимо объединить/обновить, как я могу это сделать? Чтение кода выше кажется, что добавляется и/или обновляется только один объект. – cherbear

0

Так прокомментировал я с link на уроке я писал на эту тему, но сузить ее, этот метод может помочь вам.

NSManagedObjectContext *managedObjectContext = [[SDCoreDataController sharedInstance] backgroundManagedObjectContext]; 
    // 
    // Iterate over all registered classes to sync 
    // 
    for (NSString *className in self.registeredClassesToSync) { 
     if (![self initialSyncComplete]) { // import all downloaded data to Core Data for initial sync 
      // 
      // If this is the initial sync then the logic is pretty simple, you will fetch the JSON data from disk 
      // for the class of the current iteration and create new NSManagedObjects for each record 
      // 
      NSDictionary *JSONDictionary = [self JSONDictionaryForClassWithName:className]; 
      NSArray *records = [JSONDictionary objectForKey:@"results"]; 
      for (NSDictionary *record in records) { 
       [self newManagedObjectWithClassName:className forRecord:record]; 
      } 
     } else { 
      // 
      // Otherwise you need to do some more logic to determine if the record is new or has been updated. 
      // First get the downloaded records from the JSON response, verify there is at least one object in 
      // the data, and then fetch all records stored in Core Data whose objectId matches those from the JSON response. 
      // 
      NSArray *downloadedRecords = [self JSONDataRecordsForClass:className sortedByKey:@"objectId"]; 
      if ([downloadedRecords lastObject]) { 
       // 
       // Now you have a set of objects from the remote service and all of the matching objects 
       // (based on objectId) from your Core Data store. Iterate over all of the downloaded records 
       // from the remote service. 
       // 
       NSArray *storedRecords = [self managedObjectsForClass:className sortedByKey:@"objectId" usingArrayOfIds:[downloadedRecords valueForKey:@"objectId"] inArrayOfIds:YES]; 
       int currentIndex = 0; 
       // 
       // If the number of records in your Core Data store is less than the currentIndex, you know that 
       // you have a potential match between the downloaded records and stored records because you sorted 
       // both lists by objectId, this means that an update has come in from the remote service 
       // 
       for (NSDictionary *record in downloadedRecords) { 
        NSManagedObject *storedManagedObject = nil; 
        if ([storedRecords count] > currentIndex) { 
         // 
         // Do a quick spot check to validate the objectIds in fact do match, if they do update the stored 
         // object with the values received from the remote service 
         // 
         storedManagedObject = [storedRecords objectAtIndex:currentIndex]; 
        } 

        if ([[storedManagedObject valueForKey:@"objectId"] isEqualToString:[record valueForKey:@"objectId"]]) { 
         // 
         // Otherwise you have a new object coming in from your remote service so create a new 
         // NSManagedObject to represent this remote object locally 
         // 
         [self updateManagedObject:[storedRecords objectAtIndex:currentIndex] withRecord:record]; 
        } else { 
         [self newManagedObjectWithClassName:className forRecord:record]; 
        } 
        currentIndex++; 
       } 
      } 
     } 
     // 
     // Once all NSManagedObjects are created in your context you can save the context to persist the objects 
     // to your persistent store. In this case though you used an NSManagedObjectContext who has a parent context 
     // so all changes will be pushed to the parent context 
     // 
     [managedObjectContext performBlockAndWait:^{ 
      NSError *error = nil; 
      if (![managedObjectContext save:&error]) { 
       NSLog(@"Unable to save context for class %@", className); 
      } 
     }]; 

     // 
     // You are now done with the downloaded JSON responses so you can delete them to clean up after yourself, 
     // then call your -executeSyncCompletedOperations to save off your master context and set the 
     // syncInProgress flag to NO 
     // 
     [self deleteJSONDataRecordsForClassWithName:className]; 
     [self executeSyncCompletedOperations]; 
    } 
} 
Смежные вопросы