Удалить объект из базовых данных, если он удален из канала
Рассмотрим следующую корреляцию между объектами словаря в фиде и отсортированными объектами в основных данных:
Feed CoreData
---- --------
A A
B B
C C
D D
Поскольку я перечисляю подачу, я проверяю, есть ли [stringForKey:@"name"]
равно A.name
в сущности. Если это совпадение, я обновляю сущность. Если это не так, я вставляю новую сущность в CoreData.
Это прекрасно работает для обновления и вставки, но не для удаления. Учтите, что объект C удален из канала:
Feed CoreData
---- --------
A A
B B
D C
D
Когда я получаю "D" в ленте, он видит, что объект "C" в CoreData не совпадает, и создает новый объект D. Поэтому у меня сейчас две проблемы: у меня есть два объекта "D" и объект " C "не удаляется из CoreData.
Итак, пока я хочу закончить с этим:
Feed CoreData
---- --------
A A
B B
D D
Что я сейчас получаю, так это:
Feed CoreData
---- --------
A A
B B
D C
D
D
Это должно быть распространенной проблемой, поэтому мне интересно, каков наилучший способ определения того, когда удалять сущности из Базовых данных.
2 ответа
Вот что я делаю, когда перебираю элементы, чтобы определить, обновлять, вставлять или удалять:
-(void)updateWithJSON:(id)JSON
{
//Get an array of all related managed objects
NSMutableArray *allContacts = [[NSMutableArray alloc] initWithArray:[self getAllContacts]];
//Loop through each object downloaded from the server
for (NSDictionary *objectInfo in [JSON objectForKey:@"Contacts"])
{
NSString *objectKey = [objectInfo objectForKey:@"BackendID"];
//Get the managed object for the objectKey
Contact *contact = [[allContacts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"backendID == %@", objectKey]] lastObject];
//If the object is nil, then insert the object
if (contact == nil)
{
NSLog(@"Object with key %@ is new.", objectKey);
contact = [[Contact alloc] initWithEntity:[NSEntityDescription entityForName:@"Contact" inManagedObjectContext:self.managedObjectContext] insertIntoManagedObjectContext:self.managedObjectContext];
contact.backendID = objectKey;
}
//Assign property values
contact.firstName = [objectInfo objectForKey:@"FirstName"];
contact.lastName = [objectInfo objectForKey:@"LastName"];
contact.jobTitle = [objectInfo objectForKey:@"JobTitle"];
contact.department = [objectInfo objectForKey:@"Department"];
contact.email = [objectInfo objectForKey:@"Email"];
contact.fax = [objectInfo objectForKey:@"Fax"];
contact.primaryPhone = [objectInfo objectForKey:@"PrimaryPhone"];
contact.secondaryPhone = [objectInfo objectForKey:@"SecondaryPhone"];
//Remove the object from the array of all the objects
if ([allContacts containsObject:contact])
[allContacts removeObject:contact];
}
//Delete any objects that still remain in the array (means they were deleted server-side
for (Contact *contact in allContacts) {
NSLog(@"Removing Contact with key %@", contact.backendID);
[self.managedObjectContext deleteObject:contact];
}
NSError *error = nil;
[self.managedObjectContext processPendingChanges];
[self.managedObjectContext save:&error];
if (error)
NSLog(@"Error Saving Contacts: %@", error.localizedDescription);
}
Кажется, у вас уже есть массив объектов Feed и массив объектов CoreData, оба отсортированы по одному и тому же атрибуту "name" в порядке возрастания.
Вы можете обновить / вставить / удалить объекты CoreData из объектов Feed с помощью одного цикла для обоих массивов, используя два независимых указателя на массивы.
Псевдокод выглядит так:
i1 = 0; // pointer into Feed array
i2 = 0; // pointer into CD (CoreData objects) array
while (i1 < Feed.count && i2 < CD.count) {
if (Feed[i1].name < CD[i2].name) {
// Feed[i1] is not in CD array
"Insert Feed[i1] as new Core Data object"
i1++;
} else if (Feed[i1].name > CD[i2].name) {
// CD[i2].name is not in Feed array
"Delete CD[i2] from Core Data"
i2++;
} else {
"Update CD[i2] from Feed[i1]"
i1++, i2++;
}
}
// Add remaining objects from Feed array:
while (i1 < Feed.count) {
"Insert Feed[i1] as new Core Data object"
i1++;
}
// Remove remaining Core Data objects
while (i2 < CD.count) {
"Delete CD[i2] from Core Data"
i2++;
}
В вашем примере:
Feed CoreData ---- -------- i1-> A i2-> То же имя, обновляется объект CoreData, i1++, i2++ B B ОКРУГ КОЛУМБИЯ D
Feed CoreData ---- -------- А.А. i1->B i2->B с тем же именем, объект CoreData обновлен, i1 ++, i2 ++ ОКРУГ КОЛУМБИЯ D
Feed CoreData ---- -------- А.А. B B i1->D i2->C "D" > "C", объект CoreData удален, i2 ++ D
Feed CoreData ---- -------- А.А. B B i1->D C i2->D то же имя, объект CoreData обновлен, i1 ++, i2 ++