views:

552

answers:

1

I can create an NSPredicate easily using an NSPredicateEditor (a subclass of NSRuleEditor). What I'd like to know is this:

How can I take an existing NSPredicate (one created by the editor) and reload it into the editor so that I can alter it?

EDIT: I tried @John's suggestion of using setObjectValue:, but that didn't quite work. Let me explain my set up a bit more:

I've got a Document-based cocoa app, and the Document window just has an NSPredicateEditor on it. In the dataOfType:error: method, I have:

NSPredicate * pred = [predicateEditor objectValue];
NSData * predicateData = [NSKeyedArchiver archivedDataWithRootObject:pred];
return predicateData;

In the readFromData:ofType:error: method, I have:

NSPredicate * pred = [NSKeyedUnarchiver unarchiveObjectWithData:data];
[predicateEditor setObjectValue:pred];
return (pred != nil);

I've verified that the predicate is getting correctly archived and unarchived, but after opening a saved predicate, the predicate is not loaded into the predicateEditor. (Yes, predicateEditor is hooked up as an IBOutlet)

+4  A: 

Set the objectValue property of the NSPredicateEditor to the predicate in question.

The documentation has this description of the loading process; does any of this seem like it might cause a problem with your setup?

First, an instance of NSPredicateEditor is created, and some row templates are set on it—either through a nib file or programmatically. The first thing predicate editor does is ask each of the templates for their views, using templateViews.

After setting up the predicate editor, you typically send it a setObjectValue: message to restore a saved predicate. NSPredicateEditor needs to determine which of its templates should display each predicate in the predicate tree. It does this by sending each of its row templates a matchForPredicate: message and choosing the one that returns the highest value.

After finding the best match for a predicate, NSPredicateEditor copies that template to get fresh views, inserts them into the proper row, and then sets the predicate on the template using setPredicate:. Within that method, the NSPredicateEditorRowTemplate object must set its views' values to represent that predicate.

NSPredicateEditorRowTemplate next asks the template for the “displayable sub-predicates” of the predicate by sending a displayableSubpredicatesOfPredicate: message. If a template represents a predicate in its entirety, or if the predicate has no subpredicates, it can return nil for this. Otherwise, it should return a list of predicates to be made into sub-rows of that template's row. The whole process repeats for each sub-predicate.

John Calsbeek
Edited the question with more information regarding this suggestion.
Dave DeLong
Poking around Google, there seem to be one or two quirks with `NSPredicateEditor`, but I can't find any that would cause the editor to completely ignore `-setObjectValue:`.
John Calsbeek
@John (after edit): I might be an issue. I just dropped an NSPredicateEditor from the IB Library into the window and wired it up to the MyDocument File's Owner. Do I need to do anything special with the NSPredicateEditorRowTemplates, or should the default ones work?
Dave DeLong
You will probably need to give it some `NSPredicateEditorRowTemplates`, but you should be able to do that in Interface Builder.
John Calsbeek
I found what's going on! When I open a document (archived predicate) and attempt to read it, the nib hasn't been loaded yet. I delayed setting the editor's objectValue until the nib was loaded, and then it worked perfectly. Thanks for your help, John!
Dave DeLong
That would do it, glad it works now.
John Calsbeek