苹果有一个很好的小教程来制作一个简单的主细节界面。Interface Builder甚至会从核心数据实体自动为您生成一个。然而,我正在尝试做一些比这个简单的例子更复杂的事情,我已经努力了一段时间让它工作。
我希望该界面允许用户查看主列表(NSTableView)中所有类型的页面。当他们选择一个页面时,显示的详细信息字段将取决于该页面的类型。
以下是我现在拥有的:
我有一个主nib文件,其中显示主列表,以及一个页面共有的所有字段。每个页面类型都有一个nib及其特定字段。主nib文件中有一个主NSArrayController,它正在填充NSTableView。每个页面特定的NIB中都有一个NSArrayController,这样我就可以将细节字段绑定到当前选择的属性。我所有的NSArrayController都配置相同,并且我将它们都绑定到相同的managedObjectContext和相同的SelectionIndex。
我正在使用Aaron Hillegass在其Cocoa书中描述的视图交换方法。因此,我注册了NSTableViewSelectionDidChangeNotifications,当我收到一个通知时,它会调用一个方法switchView:
switchView查看当前选定的对象,检查它是哪种类型的页面,并根据Hillegass的方法交换相应的nib文件。
如果只添加一种类型的页面,一切正常,但一旦添加第二种类型的页面,就会出现以下错误:
为对象的键路径选择索引设置值时出错(来自绑定对象实体:页,所选对象数:1):[valueForUndefinedKey:]:实体NoColPage不符合键端的键值编码。
错误的最后一部分是有意义的:它试图显示错误的nib,因此它试图绑定到该对象不存在的字段。
我在我的文档中添加了一个SelectionIndex字段,这样我的所有NSArrayController都可以绑定到同一个位置。我为这件事苦恼了好几天,但我想不出来。有什么想法吗?
如果有帮助的话,
here is a sample project you can download
编辑:
我想约书亚知道了一些事情,但不幸的是,它不起作用——我一直遇到同样的问题。起初我很难理解-unbind:需要一个字符串常量,而不是键路径。
我尝试了几种变体:跟踪当前显示的nib的阵列控制器;其中,我跟踪当前显示的页面类型,并且仅在尝试显示其他页面类型时取消绑定/重新绑定。。。
下面是代码的相关部分。
-(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];
}
}