2

ユーザーが多くの情報をセクションに整理する Core Data アプリを作成しようとしています。ポップアップ メニューと境界線のないボックスを持つメインの xib があります。そのボックスに、ポップアップ ボタンから選択されたセクションのビューを含む別の xib が読み込まれます。

補助窓の一種である 2 番目の窓/パネルを作成することにしました。メイン ウィンドウにはサマリー テーブルが表示され、アクセサリ ビューでは、サマリー テーブルで現在選択されているものを取得してテキスト フィールドやグラフィカルな日付ピッカーに表示することで、データの入力が容易になります (ユーザーにテーブルに日付を入力するための正しい形式など)。また、いくつかのオプションのフィールドを保持し、統計を表示するため、それらが私のメインビューを詰まらせることはありません.

メインの 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 ファイルについても同様です。ポップアップで選択を行うと、その送信者タグが返され、タグを受け取る別のメソッドが呼び出され、vc 配列の objectAtIndex がメイン ウィンドウ ボックスに読み込まれ、accessoryVC 配列がアクセサリ ウィンドウに読み込まれます。実際の SummaryViewController.m には次のものがあります。

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

    return self;
}

すべてのビューを作成してから、バインディングを開始しました。メイン ウィンドウのテーブル内の列が ArrangeObjects.aaa にバインドされ、アクセサリ ビューのテキスト フィールドが selection.aaa にバインドされる場合がありますが、テーブルビューの選択が変更されても、その選択は変更されません。技術的には、2 つの別々の NSArrayController を使用しているためだと思います。

セカンダリ ウィンドウのデータがメイン ウィンドウに同期されている例を書籍で見たことがありますが、両方のウィンドウが同じ xib から取得されたために機能し、同じ NSArrayController を使用していました。私の質問は、これらのオプションのどれを使用できるかです。

1) NSArrayControllers を複数の xib ファイル間で同期させる方法はありますか?

2) SummaryAccessoryView.xib のカスタム ビューを SummaryView.xib に移動して、1 つの xib にメイン ウィンドウとアクセサリ ウィンドウの両方のビューが含まれるようにすることができます。次に、NSArrayController を共有します。しかし、ポップアップで 1 つのビューをメイン ウィンドウに、もう 1 つのビューをアクセサリ ウィンドウに配置するにはどうすればよいでしょうか。私の現在の方法はに依存して[super initWithNibName: SummaryView.xib]いるため、どのビューを指定する方法がわかりません。

3) 1 ウィンドウ モデルに全体を掘り下げて再構築し、冗長なフィールドを削除して、余​​分なフィールドをメイン ビューの下部に配置できると思いますが、ユーザーはそれを非表示にしたり移動したりすることはできません。ユーザーが日付をテーブルビューにフォーマットするという問題が再び発生します...ユーザーがテーブルセルをクリックしたときにグラフィカルな日付ピッカーを表示する方法を知っていればうまくいくかもしれません。しかし、できれば 2 ウィンドウ モデルを維持したいと考えています。

オプション 1 または 2 の実行方法に関するアイデアはありますか?

編集:オプション3が機能しました:

まず、日付ピッカー (myDatePicker)、テーブル (myTable)、日付ピッカーを格納するポップオーバー (myPopover)、および NSArrayController (myArray) の ivar がいくつか必要です。また、私の例では、日付列が最初の列 (列 0) であり、IB で「日付」と名付けました。複数の日付 (開始日/終了日または 2 つのテーブルなど) がある場合は、#define を使用してフラグを設定し、必要な日付を特定する NSString ("tableAndColumn") を追加して、if ステートメントを if-複数の場合があるelse。

- (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

キー値コーディングおよびキー値監視に準拠した NIB ファイルの所有者のプロパティを使用して、NIB ファイル全体でアレイ コントローラにバインドできます。たとえば、NIB ファイルの 1 つに NSViewController サブクラスがファイルの所有者として含まれている場合、 で始まるキー パスを使用して、コントロールをファイルの所有者にバインドできますrepresentedObject

あなたの例では、ビュー コントローラー (で初期化したもの-[Document.m init]) を専用のプロパティに格納し、NSViewControllerrepresentedObjectをドキュメント インスタンスに設定できます。representedObject.myViewControllerProperty.myArrayControllerProperty次に、NIB ファイルで、 etcで始まるキー パスを使用して、コントロールをファイルの所有者にバインドできます。

私自身のアプリでは、カスタム ウィンドウ コントローラーを-[Document makeWindowControllers]使用して開始し、-initWithWindowNibNameそれをプロパティに保存しmainWCます。このメイン ウィンドウ コントローラーは、従属ビュー コントローラーを作成し (先ほど行った方法と同様)、それらのrepresentedObjectプロパティをそれ自体に設定します ( [vc setRepresentedObject:self])。他の NIB ファイル内のすべてのバインディングは、. で始まるキー パスを使用してファイルの所有者へのバインディングを介して、このメイン ウィンドウ コントローラーを介してルーティングされますrepresentedObject

同様の方法で、私のMainMenu.xibファイルは、で始まるキー パスを使用して Application オブジェクトにバインドすることにより、一部のメニュー コマンドの "Enabled" プロパティなどを適切なアレイ コントローラ プロパティに接続しますmainWindow.windowController.document.mainWC

于 2012-08-13T21:31:52.397 に答える