4

私を夢中にさせている非常に単純な質問: プログラムで NSArrayController の選択をクリアする適切な方法は何ですか?

次のコンポーネントを使用してビューを設計しています。

  • NSArrayController *controller1: オブジェクトの配列にバインド
  • NSPopUpView view1: controller1.arrangedObjects にバインドされたコンテンツ。controller1.selection にバインドされた値。「Null プレースホルダーを挿入する」が選択されました
  • NSArrayController *controller2: controller1.selection に格納されている配列にバインドされています
  • NSPopupView view2: controller2.arrangedObjects にバインドされたコンテンツ。controller2.selection にバインドされた値。「Null プレースホルダーを挿入する」が選択されました

最初に、view1 のコンテンツが入力されます。controller1 と controller2 の選択値は nil です。view1 と view2 は null プレースホルダーを表示します。controller1 を選択すると、controller1 の選択が変更され、view2 のコンテンツが読み込まれます。すべて良い。

controller1 の選択をクリアする Clear ボタンを実装したいと思います。これは、バインディングのおかげで、controller2 の選択もクリアし、view1 と view2 を null プレースホルダーにリセットする必要があります。私の人生では、この非常に単純な関数の適切なコードを理解できません。controller1 の選択を変更すると、view1 に表示される値が更新されません。さらに悪いことに、controller1 の選択をプログラムで変更すると、controller2 で奇妙なことが起こります。view1 でさらに値を選択しても、view2 には影響しません。

私が試したこと:

  • [NSArray new] を使用して controller1 の SetSelectedObjects メソッドを呼び出します。

  • null を指定して controller1 の SetSelectedObjects メソッドを呼び出します。

  • NSNotFound を使用して controller1 の SetSelectedIndex メソッドを呼び出します。

  • controller1 の SelectedIndex プロパティを使用して、controller1 の RemoveSelectedIndex メソッドを呼び出します。

  • 選択値をクリアするためのクラスメソッドまたは提案については、Cocoa NSArrayController のドキュメントを参照してください。そこには何もありません-それを達成する方法は言うまでもなく、これが望ましいことについての言及さえありません。

何か案は?ありがとう...

4

4 に答える 4

4

Apples Developer のドキュメントによると、これは setSelectionIndexes を使用して行うことができます。

すべてのインデックスを選択解除するには、空のインデックス セットを渡します。

目的 C:

[arrayController setSelectionIndexes:[NSIndexSet indexSet]];

迅速:

arrayController.setSelectionIndexes( NSIndexSet() )

于 2015-05-21T18:18:54.650 に答える
2

controller1.selectionIndex = NSIntegerMax; を試してください。それが機能するかどうかを確認します。アレイ コントローラーの選択にラベルをバインドして簡単なテストを行いました。selectionIndex を NSIntegerMax に設定すると、選択なしのプレースホルダーがラベルに表示されました。

于 2012-08-23T04:55:56.983 に答える
1

結局のところ、NSArrayController ページには、選択をクリアするための推奨事項が 1 つ含まれています。

setSelectionIndexes:

レシーバーの選択インデックスを設定し、選択が変更されたかどうかを示すブール値を返します。

(BOOL) setSelectionIndexes: (NSIndexSet *) インデックス

討論

選択を変更しようとすると、commitEditing メッセージが失敗する可能性があり、選択の変更が拒否されます。

すべてのレシーバーのオブジェクトを選択するには、インデックスはインデックス [0...count -1] で設定されたインデックスである必要があります。すべてのインデックスを選択解除するには、空のインデックス セットを渡します。

しかし、実際にそれを試してみましたが、それでも問題が残りました。

一般化するには:

  • A と B の 2 つのクラスを作成します。A には、B のインスタンスのリストを含むプロパティ「NSArray *b_list」が含まれます。

  • プロパティ「NSArray *a_list」を持つアプリケーションを作成します。これに A のいくつかのインスタンスを入力し、各 A インスタンスの b_list にいくつかの B インスタンスを入力します。

  • Controller_A (a_list にバインド) と Controller_B (Controller_A.selection.b_list にバインド) の 2 つのアレイ コントローラーを含むウィンドウを作成します。

  • ウィンドウに 2 つのポップアップ ボタン、Popup_A (Controller_A.arrangedObjects にバインド) と Popup_B (Controller_B.arrangedObjects にバインド) を作成します。

  • Controller_A の選択をクリアするロジックを含む「クリア」ボタンを作成します。(「いくつかのロジック」は、Apple のドキュメントで推奨されている方法、またはその他の方法のいずれかです。)

  • アプリケーションを実行します。Popup_A のエントリを選択します。Popup_B には Controller_A.selection.b_list のインスタンスが取り込まれることに注意してください。

  • 今すぐクリアボタンを押してください。

エラー: Popup_A のコンテンツと選択は正しく null になりますが、Popup_B では同じことが起こらないことに注意してください: 単一の選択された (空白の) 項目を持つ空白のエントリが表示されます。Controller_B の選択プロパティは選択があることを示していますが、そのプロパティは奇妙です: selectedIndex は NSNotFound ではなく 0 を指し、selectedIndexes には空でない選択整数範囲が含まれています。

これは明らかにバインディング ロジックのエラーであり、いくつかの例外や論理エラーが確実に発生する可能性があります。たとえば、B_controller.selection に何らかの種類のバインドがアタッチされている場合、A_controller をクリアすると、B_controller の選択値に関連する例外が発生します。これは、選択を示していますがガベージを指しているためです。

私の回避策は、何も B_controller 選択に直接バインドしないことです。代わりに、プログラムで B_controller にアクセスし、A_controller の選択値を考慮して、次のようにします。

// setting some property c to the value of b_controller:
if ((B_controller.selectedIndex == NSNotFound) || A_controller.selectedIndex == NSNotFound))
    c = nil;
else
    c = [B_controller objectAtIndex: [B_controller.selectedIndex]];

また、この情報とともにバグ レポートを Apple に提出しています。

于 2012-08-24T16:39:20.703 に答える
1

非常に古い質問に答えますが、それでも。

私はちょうど同じことが必要でした、そして私にとってこれはうまくいきました:

[arrayController setAvoidsEmptySelection:NO];
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:
    NSMakeRange(NSNotFound, 0)];
[arrayController setSelectionIndexes:indexes];
于 2014-07-04T07:17:39.330 に答える