English 中文(简体)
How can I create a master-detail interface with Core Data and an abstract entity?
原标题:

Apple has a nice little tutorial for making a simple master-detail interface. Interface Builder will even automatically generate one for you from a Core Data entity. However, I m trying to do something more complicated than the simple example and I ve been struggling for a while to get it to work.

I have a Core Data document-based application. The model includes an abstract entity Page, and several concrete subentities of Page. All Pages have some attributes in common (like "name") and those are defined in Page. Obviously, the subentities have the attributes that are unique to them.

I want the interface to allow the user to see all types of Pages in the master list (an NSTableView). When they select a Page, the detail fields that are displayed would depend on what kind of Page it is.

Here s what I have right now:

I have a main nib file, where the master list is displayed, plus all fields common to a Page. There s a nib for each page type with its specific fields. There s the main NSArrayController in the main nib file, which is populating the NSTableView. There s an NSArrayController in each of the page-specific nibs as well so that I can bind the detail fields to attributes of the current selection. All of my NSArrayControllers are configured identically, and I have them all bound to the same managedObjectContext and the same selectionIndexes.

I am using Aaron Hillegass s method for view swapping that he describes in his Cocoa book. So I registered for NSTableViewSelectionDidChangeNotifications, and when I receive one, it calls a method switchView:

switchView looks at the currently selected object, checks which type of Page it is, and swaps in the appropriate nib file according to Hillegass s method.

Everything works fine if I only add pages of one type, but as soon as I add a page of a second type, I get this error:

Error setting value for key path selectionIndexes of object (from bound object entity: Page, number of selected objects: 1): [ valueForUndefinedKey:]: the entity NoColPage is not key value coding-compliant for the key side.

The last part of the error makes sense: it s stuck trying to display the wrong nib, so it s trying to bind to fields that don t exist for this object.

I added a selectionIndexes field to MyDocument so that all of my NSArrayControllers could bind to the same place. I ve agonized over this for days and I can t figure it out. Any ideas?

If it helps, here is a sample project you can download. I extracted only the things relevant to this problem from my project into a new dummy application, which I ve been using to test and play around.

PS: Interface Builder s tool for generating a master-detail interface from a Core Data entity doesn t work like I want it to for abstract entities. It only creates fields for the attributes in the superentitity.

Edit: I think Joshua is on to something, but unfortunately, it doesn t work--I keep running into the same problem. At first I was having a hard time because I didn t understand that -unbind: expects a string constant, not a key path.

I ve tried several variations: where I keep track of the currently displayed nib s array controller; where I keep track of the currently displayed page type and only unbind/rebind when I m trying to display a different page type...

Here s the relevant section of code.

-(void) displayViewController: (ManagingVC *) vc withClass:(NSString*) className {

//Try to end editing
NSWindow *w = [box window];
BOOL ended = [w makeFirstResponder:w];
if (!ended) {
    NSBeep();
    return;
}

//The Managing View Controller s NSArrayController
NSArrayController* vcAc = [vc arrCont];

//if the page we re trying to switch to is NOT the same type as the current page we re displaying
//if it is, do nothing.
if (![currPageDisplayed isEqual:className]) {

    //unbind the old view controller
    ManagingVC *oldvc = [viewControllers objectForKey:className];
    NSArrayController* oldsac = [oldvc arrCont];
    [oldsac unbind:@"selectionIndexes"];

    //bind the new view controller
    [vcAc bind:@"selectionIndexes" toObject:self withKeyPath:@"selectionIndexes" options:nil];
    currPageDisplayed = className;

    NSView *v = [vc view];

    //display the new view in an NSBox in the main nib
    [box setContentView:v];
}

}

最佳回答

After spending way too much time trying to get each NIB s array controller in sync, I ve given up on that approach. The only thing that has worked for me is programmatically controlling which GUI elements are displayed in the main nib, and their bindings. This means eliminating the other nibs. This isn t really a sustainable solution if you re working with more than just a couple of text fields, but it works for me right now.

I still follow Joshua s advice of unbinding before switching the view, but right now I m only binding the text fields to arrayController.selection.whateverKey

问题回答

The problem is you re leaving your nibs array controllers bound to the document s selection, which is causing them to attempt (when the selection changes) to represent the selected item.

Try this:

  1. Remove the bindings in the nibs.
  2. Before adding a new view, connect its bindings in code.
  3. Before removing the old view, disconnect its bindings in code.

This should keep everything happy.





相关问题
Taking picture with QTCaptureView

Is it possible to simply take a picture and save it somewhere using a QTCaptureView and Apple s built-in iSight? I ve seen lots of tutorials on recording video but none on simply taking a picture. Any ...

Controlling OSX windows

I m trying to control windows of a foreign OSX applications from my application. I d like to 1. move the windows on the screen 2. resize the windows on the screen 3. change the currently active window ...

objective-c: Calling a void function from another controller

i have a void, like -(void) doSomething in a specific controller. i can call it in this controller via [self doSomething], but i don t know how to call this void from another .m file. I want to call ...

NSUndoManager and runModalForWindow:

I have a simple Core Data app which displays a list of entities in the main window. To create or add new entities, I use a second modal window with a separate managed object context so changes can be ...

NSMutableArray values becoming "invalid"

I m trying to show a database information in a tableview and then the detailed information in a view my problem is as follow: I created a NSMutableArray: NSMutableArray *myArray = [[NSMutableArray ...

How to get a flash url in a webpage using a webframe?

As we know , When we load frame from webpage of safari, we will invoke the delegate methods of webkit informal protocol(WebFrameLoadDelegate): webView:didStartProvisionalLoadForFrame: webView:...

热门标签