9

Is there a way in mantle to update an existing record in core data instead of always create new ones? This blog post looks promising, but I don't find the method updateWithJSON: somewhere in Mantle. Right now, I'm doing the following:

MantleObject *mantleObject = [MTLJSONAdapter modelOfClass:[MantleObject class] fromJSONDictionary:dictionary error:NULL];
CoreDataObject *coreDataObject = [CoreDataObject MR_findFirstByAttribute:@"primaryKey" withValue:mantleObject.primaryKey];

// avoid duplicates
if (coreDataObject != nil) {
    [coreDataObject MR_deleteEntity];
}

[MTLManagedObjectAdapter managedObjectFromModel:mantleObject insertingIntoContext:[NSManagedObjectContext MR_contextForCurrentThread] error:NULL];

It works as expected, but I don't like the idea of always deleting and creating the 'same' object over and over again. So I would love to have the opportunity of updating existing objects (overwriting is fine; ALL the values of the new object can replace the existing ones).

swalkner
  • 16,679
  • 31
  • 123
  • 210

2 Answers2

10

Mantle has supported updating managed objects since version 1.3.

Your model classes need to implement the MTLManagedObjectSerializing protocol method propertyKeysForManagedObjectUniquing and return the property keys which identify a model, which in your case appears to primaryKey:

+ (NSSet *)propertyKeysForManagedObjectUniquing {
    return [NSSet setWithObject:@"primaryKey"];
}

The header doc explains how it works, but basically the MTLManagedObjectAdapter will fetch an existing managed object if one exists and update that object rather than create a new one.

I would recommend using Mantle's built in support, rather than trying to find duplicates yourself. This will result in simpler, more maintainable code.

David Snabel-Caunt
  • 57,804
  • 13
  • 114
  • 132
  • 2
    `return [NSSet setWithObject:NSStringFromSelector(@selector(primaryKey))]` – Adam Waite Apr 08 '14 at 11:44
  • Yes, that's the safer way to do it. I didn't want to complicate the solution above. See also [`@keypath`](https://github.com/jspahrsummers/libextobjc/blob/0.4/extobjc/EXTKeyPathCoding.h) – David Snabel-Caunt Apr 08 '14 at 11:45
1

I know nothing about "mantle" or "MagicalRecord" but ...

This looks very costly indeed.
It looks as if you fetched the existing item already (in order to delete it), the missing step would be to get all properties from your MantleObject and update the existing item.

As far as CoreData goes, you could:

  1. perform the insert as you do now (keep a reference to the new object newObj)
  2. keep an array of all the managed object property keys/names you like to import props = @[@"prop1",@"prop2", ...]
  3. get the values by using dict = [newObj committedValuesForKeys:props]
  4. update the existing object [existing setValuesForKeysWithDictionary:dict]
  5. delete the newObj [context deleteObject:newObj]

if there is no existing object, simply don't delete the new object

Dan Shelly
  • 5,991
  • 2
  • 22
  • 26