Re: Core Data: Changing Transient Keys Dirties Database?
Re: Core Data: Changing Transient Keys Dirties Database?
- Subject: Re: Core Data: Changing Transient Keys Dirties Database?
- From: mmalcolm crawford <email@hidden>
- Date: Sat, 25 Jun 2005 02:11:08 -0700
On Jun 22, 2005, at 1:26 PM, Robert McNally wrote:
The point of a transient property is precisely that, although it's
not stored in the persistent store, Core Data does track changes
and register undo events for the property...
<http://developer.apple.com/documentation/Cocoa/Reference/
CoreData_ObjC/Classes/NSPropertyDescription.html#//apple_ref/doc/
uid/TP30001178-BAJHJGHJ>
That's fine, but the document you refer to says "Transient
properties are ignored by the persistent store, and not just during
saves...", however this doesn't appear to be the case-- changed
transient properties still cause an object to appear in the updated
list.
I think you're still missing the point: There is a difference between
the change management layer and the persistence layer. The
persistence layer (the actual store) does ignore transient properties
-- they are not saved to the store and (as the above document notes)
cannot be used in fetch predicates -- whereas the change management
layer does track changes to transient properties -- a change to a
transient property properly does result in an object appearing in the
update list. To see an example of why this is so, look at <http://
developer.apple.com/documentation/Cocoa/Conceptual/CoreData/Articles/
cdNSAttributes.html#//apple_ref/doc/uid/TP40001919>.
In fact, simply calling [myManagedObject
willChangeValueForKey:@"foobar"] and then [myManagedObject
didChangeValueForKey: @"foobar"] on a key that neither appears in
the model nor anywhere else in my application ("foobar" in this
example) STILL causes the object to appear in
[myManagedObjectContext updatedObjects], and hence causes
[myManagedObjectContext save:] to re-write the data store.
Invoking the change notification methods flags an object as having
changed.
You can probably work about it by disabling undo registration:
- (void)setCurrentDate:(NSDate *)aDate
{
if (date != aDate) {
NSManagedObjectContext *moc = [self managedObjectContext];
[moc processPendingChanges];
[[moc undoManager] disableUndoRegistration];
[self willChangeValueForKey:@"currentDate"];
[currentDate release];
currentDate = [aDate retain];
[self didChangeValueForKey:@"currentDate"];
[[moc undoManager] enableUndoRegistration];
}
}
Finally, I notice that this seems to have something to do with
the Undo machinery, because I am able to perform an "undo"
immediately after the minute-timer fires, and if I perform that
Undo, then the database is no longer dirty. I tried surrounding
my willChange/didChange calls
Umm, what willChange/didChange calls...
[myManagedObject willChangeValueForKey:] and [myManagedObject
didChangeValueForKey:]
In general there should be no reason to invoke these methods on any
object other than self.
[...]
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)
object change:(NSDictionary*)change context:(void*)context
{
if([keyPath isEqualToString:@"currentDate"] && object ==
[CAppController appController]) {
// The following triggers observers of the "overdue" attribute
// to update their display of this task. It also
// registers a spurious Undo event, and it also spuriously
// adds this task to the set of changed objects in the
// managed object context. I want it only to trigger the
// update notifications for dependent keys.
[self willChangeValueForKey:@"currentDate"];
[self didChangeValueForKey:@"currentDate"];
}
}
You should not do this. The change notification method invocations
should surround the actual change. See the implementation of
setCurrentDate: above.
You'll probably also need to invoke processPendingChanges, but
it's difficult to say more without knowing exactly what you're
doing and why.
Exactly under what circumstances to use processPendingChanges
remains a mystery to me. Perhaps the detail I provide above can
help you tell me whether this is such a case.
processPendingChanges causes undo events to be registered.
It's not clear that model objects should be observing something in
the application. You should probably be sending messages to the
model objects from a controller.
While you may be right, as my current pattern causes every fetched
task to listen to the "currentDate" attribute of the app
controller, I don't see how implementing it differently would
result in a fix in my particular situation
It wouldn't -- the comment was about general architecture. Your
model objects generally shouldn't have direct access to an app
controller.
mmalc
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden