6

コンテキスト を表示すると、予期しない結果が発生しましたNSMenumenuのプロパティを使用せずに、自分でメニューを提示していますNSResponderNSMenuを提示することはブロッキング操作であることが判明しました。

新しいテンプレート プロジェクトでは、次のコードのみを追加しましたapplicationDidLaunch:

NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Menu"];
[menu addItemWithTitle:@"Item 1" action:@selector(selected:) keyEquivalent:@""];
[menu addItemWithTitle:@"Item 2" action:@selector(selected:) keyEquivalent:@""];
[menu addItemWithTitle:@"Item 3" action:@selector(selected:) keyEquivalent:@""];
[menu popUpMenuPositioningItem:[menu itemAtIndex:0] 
                    atLocation:CGPointMake(500, 500) 
                        inView:nil];
NSLog(@"Context menu shown.");

popUpMenuPositioningItem:atLocation:inView:アイテムを選択するか、外側をクリックしてメニューを自動的に閉じるまで、呼び出しは返されません。ログは、メニューが閉じられたときにのみ印刷されます。

なぜこれが起こるのですか?どうすればそれを防ぐことができますか?この問題についての言及がいくつか見つかりましたが、「解決策」は常に、NSMenuブロックを防ぐのではなく、バックグラウンドで他のことを実行することで構成されていました。

編集:

メニューをバックグラウンド スレッドで表示すると、メニューが応答しなくなり、内部または外部のクリックに反応しなくなります。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    [[menu popUpMenuPositioningItem:[menu itemAtIndex:0] 
                         atLocation:CGPointMake(500, 500) 
                             inView:nil];
});
4

1 に答える 1

2

あなたが求めていることが可能だとは思いませんが、非常に似ているように見えるいくつかのことができます:

1) メニューの代わりに NSPopover を使用します。これは非同期であり、ポップアップ メニューを使用できる多くのコンテキストで使用することを目的としています。ポップオーバーがない OS バージョンをサポートする必要がある場合は、いつでもボタンを含む NSWindow を作成することもできます。

2) タイマー、または実行ループでスケジュールされているその他の操作 (ダウンロードなど) を実行しようとしている場合は、NSEventTrackingRunLoopMode でこれらをスケジュールできます。デフォルトでは、それらは NSDefaultRunLoopMode に対してのみスケジュールされます (アラートを表示するタイマーがトリガーされたときにユーザーのメニュー選択をキャンセルしたくないため、これは理にかなっています)。

正直なところ、あなたがやろうとしていることは、無意味で、混乱を招き、逆行しており、メニューを乱用しているように思えます。しかし、それはおそらく、あなたが何を達成しようとしているのかわからないからです. あなたの高レベルの仕事は何ですか?メニューが起動している間にメインスレッドで何が起こる必要があるのですか? 他のこと (あなたの例では NSLog()) を 2 番目のスレッドで実行し、メニューをメイン スレッドのままにすることはできませんか?

于 2013-04-21T13:57:21.103 に答える