hpique
hpique

Reputation: 120334

Calculated properties in Core Data

Consider an Core Data entity with two properties: text and -for the sake of simplicity- textLength. textLength is a property that is calculated every time text changes. I have three requirements:

  1. Update textLength every time text changes, ideally inside the NSManagedObject subclass.
  2. textLength cannot be calculated on demand for performance reasons (the actual calculated property that I'm using is much more expensive to calculate).
  3. Update the UI every time text changes.

My solution is almost there. I'm providing a custom accessor for setText:, like this:

- (void)setText:(NSString *)text
{
    static NSString *key;
    if (!key) key = NSStringFromSelector(@selector(text));
    [self willChangeValueForKey:key];
    [self setPrimitiveText:text];
    self.textCount = text.count;
    [self didChangeValueForKey:key];
}

And using KVO in the UI to observer text changes:

[someObject addObserver:self forKeyPath:NSStringFromSelector(@selector(text)) options:NSKeyValueObservingOptionNew context:someContext];

This works fine in most cases, except when I perform undo. I take that Core Data calls setPrimiteValue:forKey: directly, and this does not trigger my calculation logic. As a consequence, when the UI is notified of the change, the textLength value is outdated.

Short of calculating textLength on demand, where should the calculation logic be?

Upvotes: 1

Views: 271

Answers (1)

Wain
Wain

Reputation: 119031

This is the purpose of the - (void)awakeFromSnapshotEvents:(NSSnapshotEventType)flags method. It tells you the reason for the snap shot change and allows you to update computed / derived data.

(when you update the derived value you should set it using the appropriate primitive method)

Upvotes: 1

Related Questions