Удалить объект из базовых данных, если он удален из канала

Рассмотрим следующую корреляцию между объектами словаря в фиде и отсортированными объектами в основных данных:

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 ++
Другие вопросы по тегам