我正在尝试创建一个Core Data应用程序,用户将很多信息组织成各个部分。我有一个主xib,有一个弹出菜单和一个无边框。在该框中,将加载一个单独的xib,其中包含从弹出按钮中选择的部分的视图。
我决定制作第二个窗口/面板,这是一个辅助窗口。这个想法是主窗口显示一个摘要表,而附件视图通过在摘要表中选择当前选择并在文本字段,图形日期选择器中显示它来更容易输入数据(而不是强制用户使用用于在表格中输入日期的正确格式等等。它还包含一些可选字段并显示统计数据,因此不会阻塞我的主视图。
主要xib的My Document.m有:
- (id)init
{
self = [super init];
if (self) {
viewControllers = [[NSMutableArray alloc] init];
accessoryViewControllers = [[NSMutableArray alloc] init];
ManagingViewController *vc;
ManagingViewController *accessoryVC;
vc = [[SummaryViewController alloc] init];
accessoryVC = [[SummaryAccessoryViewController alloc] init];
[vc setManagedObjectContext: [self managedObjectContext]];
[accessoryVC setManagedObjectContext: [self managedObjectContext]];
[viewControllers addObject: vc];
[accessoryViewControllers addObject: accessoryVC];
}
return self;
}
依此类推其他将在弹出按钮中列出的viewControllers / xib文件。在弹出窗口中进行选择将返回其sender标签,然后调用另一个接收标签的方法,并将vc数组中的objectAtIndex加载到主窗口框中,并将accessoryVC数组加载到附件窗口中。在实际的SummaryViewController.m中,我有:
- (id) init {
self = [super initWithNibName: @"SummaryView" bundle:nil];
if (self) {
[self setTitle: @"Summary"];
}
return self;
}
我构建了所有视图,然后开始绑定。主窗口中的表中的列可能绑定到arrangeObjects.aaa,附件视图的textfield将绑定到selection.aaa,但是当tableview选择更改时,其选择不会更改。我猜这是因为从技术上讲他们使用的是两个独立的NSArrayControllers。
我已经看过书中的例子,其中辅助窗口的数据与主窗口同步,并且它起作用,因为两个窗口都来自相同的xib,因此它们使用相同的NSArrayController。我的问题是,我可以使用以下哪些选项:
1)有没有办法让NSArrayControllers在多个xib文件中保持同步?
2)我可以将SummaryAccessoryView.xib中的自定义视图移动到SummaryView.xib中,以便一个xib包含主窗口和附件窗口的视图。然后他们将共享NSArrayControllers。但是,如何让我的弹出窗口将一个视图放在主窗口中,另一个放在附件窗口中?我当前的方法依赖于[super initWithNibName: SummaryView.xib]
所以我没有看到任何方法来指定哪个视图。
3)我想我可以将整个事物塌陷并重建为单窗口模型,废弃冗余字段并将额外字段放在主视图的底部,但用户将无法隐藏它或者移动它我再次遇到这个问题,让用户将他们的日期格式化为一个tableview ...如果我知道如何在用户点击表格单元格时出现图形日期选择器,它可能会有效。但如果可能的话,我宁愿保留双窗口模型。
关于如何做选项1或2的任何想法?
编辑:我有选项3工作:
首先需要一些ivars:日期选择器(myDatePicker),你的表(myTable),包含日期选择器的弹出窗口(myPopover)和NSArrayController(myArray)。同样在我的例子中,日期列是第一列(第0列),我在IB中将其命名为“date”。如果您有多个日期(如开始/结束日期或两个表),您可以添加一个NSString(“tableAndColumn”),它使用#define设置标志以标识您需要的日期,并将您的if语句转换为if-其他有多个案例。
- (BOOL) tableView:(NSTableView *)tableView
shouldEditTableColumn:(NSTableColumn *)tableColumn
row:(NSInteger)row {
if (tableColumn == [myTable tableColumnWithIdentifier: @"date"]) {
//tableAndColumn = myStartDate;
[myDatePicker setDateValue: [myArray valueForKeyPath: @"selection.date"]]; //this will set your date picker to the value already in the table column
NSRect rect = [myTable frameOfCellAtColumn: 0 row: [myTable selectedRow]];
[myPopover showRelativeToRect: rect ofView: myTable preferredEdge:NSMaxYEdge];
return NO;
// } else if (tableColumn == [myTable tableColumnWithIdentifier: @"endDate"]) {
// ...
} else {
return YES;
}
}
- (void) popoverWillClose:(NSNotification *)notification {
// if ([tableAndColumn isEqualToString: MyStartDate]) {
[myArray setValue: [myDatePicker dateValue] forKeyPath: @"selection.date"];
// } else if ([tableAndColumn isEqualToString: MyEndDate]) {
// ...
// }
}
答案 0 :(得分:1)
您可以使用NIB文件所有者的属性绑定到NIB文件中的数组控制器,这些属性是键值编码和键值观察符合性。例如。如果您的一个NIB文件将NSViewController子类作为文件的所有者,则可以使用以representedObject
开头的关键路径将控件绑定到文件的所有者。
在您的示例中,您可以将视图控制器(在-[Document.m init]
中初始化)存储在专用属性中,并将NSViewController的representedObject
设置为文档实例。然后,在您的NIB文件中,您可以使用以representedObject.myViewControllerProperty.myArrayControllerProperty
等开头的密钥路径将控件绑定到文件的所有者。
在我自己的应用中,我使用-[Document makeWindowControllers]
在-initWithWindowNibName
中启动自定义窗口控制器并将其存储在mainWC
属性中。此主窗口控制器创建从属视图控制器(类似于您的操作方式)并将其representedObject
属性设置为自身([vc setRepresentedObject:self]
)。然后,使用以representedObject
开头的关键路径通过绑定到文件所有者,通过此主窗口控制器路由其他NIB文件中的所有绑定。
以类似的方式,我的MainMenu.xib
文件连接例如某些菜单命令的“Enabled”属性通过使用以mainWindow.windowController.document.mainWC
开头的键路径绑定到Application对象来适当的数组控制器属性。