2

I have entities that all have createdAt and updatedAt properties. What I am trying to do is to set the value of those attributes automatically upon insert/update.

After doing some research, I found out that there is an awakeFromInsert method which I could use to set the value of the createdAt property automatically when a new object is created.

However, I could not find anything similar for updating an object. So what should I do? Do I have to update the updatedAt property manually every time?

Robert Audi
  • 8,019
  • 9
  • 45
  • 67

2 Answers2

0

It depends what you want to achieve. Updating only on save you could do at:

-(void)willSave;

Remember that modifying properties at this place will call willSave again. So, you have to update updatedAt only once. Also, You have to check that the object wasn’t deleted - isDeleted.

You may also observe all properties and set updatedAt to date when it was really updated, not saved.

thom_ek
  • 673
  • 4
  • 7
  • Thanks for the quick answer. However, I ended up doing something slightly different (see my own answer to the question). – Robert Audi Jun 09 '14 at 14:51
  • Doing such things globally on +load is imo bad idea. For me, better place is to watch such notifications on managedObjectContext in your appDelegate or wherever you had core data management. – thom_ek Jun 10 '14 at 11:44
0

I ended up finding similar questions/answers on StackOverflow (https://stackoverflow.com/a/10723861/123016 and https://stackoverflow.com/a/4590190/123016). I adapted the suggested solutions to suit my needs.

What I first did, is create an abstract entity which I used as the parent class of all other entities. This abstract class has two properties: createdAt and updatedAt.

I then added the following code to the implementation of the abstract class:

- (void)awakeFromInsert
{
    [super awakeFromInsert];

    self.createdAt = [NSDate date];
}

+ (void)load
{
    @autoreleasepool {
        [[NSNotificationCenter defaultCenter] addObserver:(id)self.class
                                                 selector:@selector(objectContextWillSave:)
                                                     name:NSManagedObjectContextWillSaveNotification
                                                   object:nil];
    }
}

+ (void)objectContextWillSave:(NSNotification *)notification
{
    NSManagedObjectContext *context              = [notification object];
    NSSet                  *allObjects           = [context.insertedObjects setByAddingObjectsFromSet:context.updatedObjects];
    NSPredicate            *predicate            = [NSPredicate predicateWithFormat:@"self isKindOfClass: %@", [self class]];
    NSSet                  *allModifiableObjects = [allObjects filteredSetUsingPredicate:predicate];

    [allModifiableObjects makeObjectsPerformSelector:@selector(setUpdatedAt:) withObject:[NSDate date]];
}

Apart from the fact that I made the parent class abstract, this is exactly the same code as both answers combined.

Community
  • 1
  • 1
Robert Audi
  • 8,019
  • 9
  • 45
  • 67
  • Creating an abstract parent entity for all of your managed objects is a bad idea. They will all be stored in the same SQL table and your database performance will suffer. – jrturton Jun 09 '14 at 14:58
  • You'd be better off creating some other object to listen to the notifications, and update the relevant property if the updated objects have the appropriate property – jrturton Jun 09 '14 at 14:59
  • Ah! Didn't think of that (bad move from me) ... However, if I created another object that listens to the notifications and then update the relevant properties, wouldn't I be updating the records twice? And if that is the case, wouldn't that also affect performance? – Robert Audi Jun 09 '14 at 15:03
  • The performance I'm talking about is for your fetching and lookups and inserts and pretty much everything. In terms of the code that's happening above, the database updates will be exactly the same - all you've done is save repeating yourself by subscribing lots of different classes to the notification. – jrturton Jun 09 '14 at 15:08