My document-based Cocoa application uses a NSOutlineView/NSTreeController combo, bound to the document's Core Data store. My NSTreeController has the fetch predicate isRoot == YES
. isRoot
is a transient boolean attribute with a default value of NO
. My root model's awakeFromInsert
calls:
[self setIsRoot:[NSNumber numberWithBool:YES]];
I'm able to add objects to the hierarchy just fine, but when I try to load a document I just saved, I get an exception:
[<NSDictionaryMapNode 0x1001a8190> valueForUndefinedKey:]: this class is not key value coding-compliant for the key isRoot.
I can work around this exception and successfully load a newly-saved document if I change the isRoot
attribute to non-transient in the xcdatamodel, but based on my understanding of the transient flag it should not cause a problem, and this really isn't the kind of data that should be persisted.
I have also tried implementing -isRoot
in the NSManagedObject su开发者_StackOverflowbclasses to return the appropriate fixed value, as well as making the same setIsRoot:
call within awakeFromFetch
, both to no avail.
Is there some other subtlety I'm missing? I can't imagine that fetch predicates don't support transient attributes. I don't know much about the inner workings of Core Data but it seems interesting that it's trying to look up isRoot
on the store-specific class and not my NSManagedObject subclass.
I can't imagine that fetch predicates don't support transient attributes.
After a bit of research, I can tell you that they don't. See this document. Quote:
You cannot fetch using a predicate based on transient properties (although you can use transient properties to filter in memory yourself).
I've put together a test project and can verify I get exactly the same error as you do.
When I need to filter out the root nodes in a tree, I use a fetch predicate of parent == nil
instead of a transient attribute.
I understand your reaction - I too wanted way of having an attribute specifically called isRoot too. My guess is it's possible, but it'd take so much code it's just not worth the hassle.
Oh, and if you're dealing with core data any more than a little, mogenerator will make your life much easier.
Another option is to have a separate class for the top-level nodes, use that class name as "Entity Name" and leave "Fetch Predicate" blank. As long as the child nodes have the same values as the top-level node (I use a common superclass/entity inheritance), everything still works.
Have you made sure that the NSTreeController is set to control an entity rather than a class?
From your error, it looks like it might be set to a class with the default - NSMutableDictionary.
I'd also argue that maybe isRoot could be persisted. It depends on what you're trying to do with your app, of course, but if it's a tree view that gets loaded on app run I'd either make isRoot persist.
精彩评论