Re: Core Data: undo and non-object attribute
Re: Core Data: undo and non-object attribute
- Subject: Re: Core Data: undo and non-object attribute
- From: Jakob Olesen <email@hidden>
- Date: Sun, 15 Oct 2006 12:11:12 +0200
On 14/10/2006, at 22.18, Matteo Rossi wrote:
Undo/redo is operating on the primitive values stored by the
NSManagedObject. You never set the primitive values for the x and
y keys, so they are always nil as far as the undo manager is
concerned.
I've tried adding [self setPrimitiveValue:[NSNumber
numberWithDouble:value] forKey:@"x"] but it doesn't work anyway.
It would work if you also used [primitiveValueForKey:]
Or perhaps you're suggesting that I should manage undo in my own
setPrimitiveValue:forKey?
Nonono, don't even think about it.
What exactly are you trying to achieve? Did you read the
documentation about ivars in NSManagedObject?
The problem is that I'm using a C-Structure as ivar.
Yes, the question is why are you doing that?
CD doesn't seem to like it. In fact, docs report:
"If you choose to represent an attribute using a scalar type (such
as int or float), or as one of the structures supported by
NSKeyValueCoding (NSRect, NSPoint, NSSize, NSRange), then you
should implement accessor methods as illustrated in Listing 2. If
you want to use any other attribute type, then you should use a
different pattern, described in Non-Standard Attributes."
But it's not clear for me.
I don't blame you. The situation with instance variables,
primitiveValueForKey:, and valueForKey: is a little confusing.
Here is one way of thinking about it:
A managed object has two layers: Guts and skin.
The guts is what you access with primitiveValueForKey: It provides
storage for all the properties in the entity.
[primitiveValueForKey:@"foo"] looks for the value in three places:
1. A primitive accessor method -[primitiveFoo]
2. An instance variable named "foo". (Probably also "_foo")
3. NSManagedObject's internal storage. This is where everything is
stored by default.
The guts is simply a way of storing values, nothing more. Think of it
as an extension of instance variables. It does not send KVO
notifications or anything. You can only store KVC compliant values,
though.
The outer layer, the skin, is what you access with valueForKey: It is
a wrapper around the guts that makes the object easier to use. It
makes sure that willAccess/didAccess/willChange/didChange methods are
called, and you can add business logic here, if you want.
[valueForKey:@"foo"] does one of two things:
1. Either use a custom accessor method if it exists -[foo]
2. Or use primitiveValueForKey:@"foo" properly wrapped by willAccess/
didAccess calls.
Now, Core Data is all about the guts. Fetching and saving use the
guts. Undo and redo use the guts. Core Data does not really care
about the skin.
Core Data makes the very important assumption that all the state of
an object is stored in the guts. When you perform an undo operation,
Core Data simply changes the guts back the the old values. It does
not call your custom accessor methods to do that - they are skin
methods, and Core Data does not care about the skin.
The reason your code is not working with undo is that you are keeping
your state outside the guts. That is bad. Sure, you are moving values
in and out of the guts when fetching and saving, but there are no
such call backs for undo. The undo manager is recording and restoring
what is in the guts, and your code is ignoring it.
Actually that it the only thing your code is doing. You have cleverly
created an object with two double attributes, x and y, that behave
like normal attributes except they don't support undo.
That is not what you were trying to do, but it is not easy to see,
what you really are trying to do. Why do you need to keep x and y in
a struct instance variable?
_______________________________________________
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