2

我正在尝试创建一个核心数据应用程序,用户将大量信息组织成部分。我有一个主 xib,它有一个弹出菜单和一个无边框框。在该框中,将加载一个单独的 xib,其中包含从弹出按钮中选择的部分的视图。

我决定制作第二个窗口/面板,它是一种辅助窗口。这个想法是主窗口显示一个汇总表,而辅助视图通过在汇总表中获取当前选择并将其显示在文本字段、图形日期选择器中(而不是强制用户使用在表格中输入日期的正确格式)等。它还包含一些可选字段并显示统计信息,因此这些不会阻塞我的主视图。

我的主要 xib 的 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 文件,依此类推。在弹出窗口中进行选择会返回其发送者标记,然后调用另一个获取该标记的方法,并将 vc 数组中的 objectAtIndex 加载到主窗口框,并将 accessoryVC 数组加载到辅助窗口中。在实际的 SummaryViewController.m 中,我有:

- (id) init {
    self = [super initWithNibName: @"SummaryView" bundle:nil];
    if (self) {
        [self setTitle: @"Summary"];
    }

    return self;
}

我构建了所有视图,然后开始绑定。主窗口表格中的一列可能会绑定到arrangedObjects.aaa,而辅助视图的文本字段将绑定到selection.aaa,但是当tableview 选择发生变化时,它的选择不会改变。我猜那是因为从技术上讲,他们使用的是两个独立的 NSArrayController。

我在书中看到了一些示例,其中辅助窗口将数据同步到主窗口,它之所以有效,是因为两个窗口都来自同一个 xib,因此它们使用了相同的 NSArrayController。我的问题是,我可以使用以下哪些选项:

1)有没有办法让 NSArrayControllers 在多个 xib 文件中保持同步?

2) 我可以将 SummaryAccessoryView.xib 中的自定义视图移动到 SummaryView.xib 中,以便一个 xib 包含主窗口和辅助窗口的视图。然后他们将共享 NSArrayControllers。但是,如何让我的弹出窗口将一个视图放在主窗口中,将另一个视图放在附件窗口中?我目前的方法依赖于[super initWithNibName: SummaryView.xib]所以我看不到任何方法来指定哪个视图。

3)我想我可以将整个东西转换为单窗口模型,废弃多余的字段并将额外的字段放在我的主视图的底部,但用户将无法隐藏或移动它它周围,我再次遇到这个问题,让用户将他们的日期格式化为表格视图......如果我知道如何在用户单击表格单元格时出现图形日期选择器,它可能会起作用。但如果可能的话,我更愿意保留双窗口模型。

关于如何执行选项 1 或 2 的任何想法?

编辑:我得到了选项 3 的工作:

您首先需要一些 ivars:日期选择器 (myDatePicker)、您的表 (myTable)、包含日期选择器的弹出框 (myPopover) 和 NSArrayController (myArray)。同样在我的示例中,日期列是第一列(第 0 列),我在 IB 中将其命名为“日期”。如果您有多个日期(如开始/结束日期或两个表格),您可以添加一个 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]) {
//       ...
//    }
}
4

1 回答 1

1

You can bind to your array controllers across NIB files by using properties of your NIB file's owner that are key-value coding and key-value observing compliant. E.g. if one of your NIB files has your NSViewController subclass as the file's owner, you can bind controls to the file's owner using key paths that start with representedObject.

In your example, you could store your view controllers (which you initialized in -[Document.m init]) in dedicated properties, and set the NSViewController's representedObject to the document instance. Then, in your NIB file, you could bind your controls to the file's owner using a key path that starts with representedObject.myViewControllerProperty.myArrayControllerProperty etc.

In my own app, I initiate a custom window controller in -[Document makeWindowControllers] using -initWithWindowNibName and store it in a mainWC property. This main window controller creates subordinate view controllers (similar to how you've done it) and sets their representedObject property to itself ([vc setRepresentedObject:self]). All bindings in other NIB files are then routed thru this main window controller via bindings to file's owner using key paths that start with representedObject.

In a similar fashion, my MainMenu.xib file connects e.g. the "Enabled" property of some menu commands to appropriate array controller properties by binding to the Application object using key paths that start with mainWindow.windowController.document.mainWC.

于 2012-08-13T21:31:52.397 回答