2
  1. メインメニューのウィンドウアイテムサブメニューとしていくつかのサブメニューを挿入しました
  2. NSObject から継承されたオブジェクトのインスタンス (クラス名は MenuController と仮定しましょう) があり、NSMenuDelegate メソッドから 2 つをサポートしています。 – numberOfItemsInMenu: – menu:updateItem:atIndex:shouldCancel:
  3. このインスタンスは、実行時に起動するために Blue-Object として NIB に追加されました
  4. サブメニューのデリゲートとして構成された手順 2 ~ 3 のオブジェクト (手順 1)

これで、実行時にサブメニュー コンテンツを提供できるようになりました。

次に、次のことを行います。プロトコルとデリゲートを介して実際のサブメニューにマップされた配列 (メニュー タイトルを含む MenuController 内) に新しい項目を追加したり、古い項目を削除したりできます。すべて正常に動作します。ただし、動的なメニュー項目にショートカットを割り当てるのが好きです。CMD-1、CMD-2、CMD-3など

ウィンドウ / MySubmenu / MyItem1 CMD-1、MyItem2 CMD-2、...

したがって、いくつかのアイテムを呼び出すには、Window / MySubmenu / MyItem に移動してマウスでクリックしたくないので、CMD-3 などのショートカットを 1 つだけ押してアイテムを呼び出します。

わかりました、定期的に期待どおりに動作します。しかし、通常、ネストされたサブメニューの変更についてメイン メニューに通知する方法はありません。問題を再現するための 1 つの安定した方法 - 削除済みの代わりに新しいアイテムを作成した後、いくつかのアイテムを削除して、それに割り当てられた古いショートカットを押してみてください - ビンゴ - 現在のサブメニュー コンテンツを表示するために Window / MySubmenu に移動する前にショートカットが機能しません.

メインメニューにサブメニューを強制的に再構築する方法がわかりません...私は試しました: [[NSApp mainMenu] update] と、NSMenuDidAddItemNotification、NSMenuDidRemoveItemNotification、NSMenuDidChangeItemNotification を送信するために NSNotificationCenter を使用したゲーム

サブメニューへのアウトレットを試み、メソッドを明示的に更新するようにしました-方法はありません... AppKitがデリゲートメソッドを呼び出す場合があります-そして、何も呼び出したくない場合もあります。ランダムな戦略のように見えます。

「何らかの呼び出し」の後、サブメニューが内部配列の変更後に実際の状態になることを確認するにはどうすればよいですか?

4

3 に答える 3

5

1:1マッピングを実装するには、次の3つのメソッドをデリゲートで実装します。

- (BOOL)menu:(NSMenu *)menu
updateItem:(NSMenuItem *)item 
atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel

- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu

- (void)menuNeedsUpdate:(NSMenu *)menu
{
    if (!attachedMenu)
        attachedMenu = menu;
    if (!menu)
        menu = attachedMenu;
    NSInteger count = [self numberOfItemsInMenu:menu];
    while ([menu numberOfItems] < count)
        [menu insertItem:[[NSMenuItem new] autorelease] atIndex:0];
    while ([menu numberOfItems] > count)
        [menu removeItemAtIndex:0];
    for (NSInteger index = 0; index < count; index++)
        [self menu:menu updateItem:[menu itemAtIndex:index] atIndex:index shouldCancel:NO];
}

attachMenu-タイプNSMenu*の内部変数です

次に、いつでもサブメニューを強制的に更新したい場合は、

[self menuNeedsUpdate:nil];
于 2010-02-10T12:30:37.407 に答える
3

試してみました: [[NSApp mainMenu] update] …</p>

あなたは正しい軌道に乗っています。これは、Cocoa アプリの並列配列が保証される 1 つの状況かもしれません。

  1. メニュー項目が表すモデル オブジェクトの配列と並行して、メニュー項目の可変配列を保持します。
  2. を受け取ったらnumberOfItemsInMenu:、持っているモデル オブジェクトの数とメニュー項目配列の数を比較します。少ない場合はremoveObjectsInRange:メソッドを使用してメニュー項目配列を短くします。それ以上の場合は、配列をNSNullオブジェクトで埋めます。( nilNSArray にはオブジェクトのみを含めることができ、オブジェクトがnil存在しないため、ここでは使用できません。)
  3. を受け取ったら、配列内のそのインデックスのオブジェクトを新しいメニュー項目に置き換えてからmenu:updateItem:atIndex:shouldCancel:、新しいメニュー項目を返します。
  4. メソッドのドキュメントにupdate記載されているように、NSMenuValidation プロトコルに準拠します。検証メソッドで、配列内のメニュー項目のインデックスを見つけてから、モデル オブジェクト配列内のそのインデックスにあるモデル オブジェクトを取得し、そこからメニュー項目を更新します。Snow Leopard を使用している場合は、メニュー項目のメニューにpropertiesToUpdateメッセージを送信して、モデル オブジェクトから付与する必要があるプロパティ値を決定できます。

注意点として、メニューのデリゲートであるこのオブジェクトは、メニュー項目のターゲットでもある必要があります。だと思います。そうでない場合、検証メッセージがメニュー項目のターゲットに送信されるため、これはステップ 4 で失敗します。

より良い方法を求める拡張要求を提出することをお勧めします。

于 2010-02-10T09:11:25.490 に答える