0

私は現在、Titanium Appcelerator Desktop SDK に欠けていると感じた機能を実装することによって (実行することで) Objective-C を学習しています: カスタム ボタン テキストでモーダル ダイアログを実行し、オプションでそれらを「シート」として表示する方法。

すべてがダンディで機能していますが、NSAlert を「シート」として表示すると、アラートを作成しているメソッドがすぐに返され、それを防ぎたいのです。

メソッドがアラートを作成すると、int (NSAlert からの戻りコード) が返されます。

内部のコードは基本的に次のようになります。

int returnCode = -1;
if (displayAsSheet) {
    [alert beginSheetModalForWindow:nativeWindow modalDelegate:delegate didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil];

} else {
    returnCode = [alert runModal];
}

return returnCode;

modalDelegate は、必要なものを実装するオブジェクトです。

- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;

今のところ、returnCode の NSLog を実行するだけです。

だから私の質問は:

「シート」が閉じられるまで、メソッドが返されないようにするにはどうすればよいですか?

それとも、これについて間違った方法で行っていますか?

4

5 に答える 5

4

シートを表示した後にモーダル セッションを開始し、シートを閉じた後にセッションを停止する必要があります。

これを確認してください: https://github.com/incbee/NSAlert-SynchronousSheet、役立つと思います。

于 2011-11-10T19:39:45.847 に答える
1

あなたは後にこれを使うことができますbeginSheetModalForWindow:...

[[NSRunLoop mainRunLoop] runMode:NSModalPanelRunLoopMode beforeDate:[NSDate distantFuture]]

ただし、シートが閉じられるまで、アプリ内の他のウィンドウは使用できなくなります。それらのウィンドウをブロックしない方がよいでしょう。

于 2011-11-10T18:55:23.233 に答える
1

アラートを作成している私のメソッドはすぐに戻ります

@Joshが言うように、シートはそれが接続されているウィンドウに対してのみモーダルで実行されているためだと思います。アプリ全体がフリーズするわけではありません。したがって、実行するとすぐに、ユーザーがアラートに応答するのを待たずにbeginSheetModal...、メソッドの残りの部分が実行され続け、(ここでは -1 を返します) で終了します。return returnCode

リターン コードは、ユーザーが最終的にプッシュするアラート パネルのボタンの代用です (NSAlertFirstButtonReturn、NSAlertSecondButtonReturn など - これらは NSAlert クラス ref の最後にリストされています)。メソッドでこれを使用してalertDidEnd、ユーザーがアラートを閉じるために押したボタンに応じて動作します。そのため、alertDidEndセレクターには returnCode が含まれています。

一方、ブロック内でrunModalメソッドを使用する場合は、メソッドを明示的に呼び出して、メソッドが終了したときに返される数値を渡す必要があります。これは、ユーザーがアラートを閉じたときです。elsealertDidEndrunModal

コードの改訂版は次のとおりです。

int returnCode = -1;
if (displayAsSheet) {
    [alert beginSheetModalForWindow:nativeWindow modalDelegate:delegate didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil];
    // The selector alertDidEnd has the returnCode int. The alert will then set that code to whatever the user chooses, and will send the altered int on to alertDidEnd.
} 
else {
    // Here, everything stops once runModal is called, until the user dismisses the alert, at which time the runModal method returns the int representing the button the user pushed, and you assign the return to your variable "returnCode."
    returnCode = [alert runModal];
    [self alertDidEnd:alert returnCode:returnCode contextInfo:nil];
}
// Omit the line returning the returnCode.

次に、alertDidEndメソッドは次のようなことを行います。

- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { 
switch (returnCode) {
    case NSAlertFirstButtonReturn:
        // Do whatever should happen when first button is pushed.
        break;
    case NSAlertSecondButtonReturn: 
        // Do whatever should happen when second button is pushed.
        break;
    default:
        break;
    }
    // Unfreeze things.
    [[NSApplication sharedApplication] stopModal];
}

ちなみに、必要応じて、シートを実行して、シートが添付されているウィンドウだけでなく、アプリ全体をフリーズする方法があります:モーダル ヒント

于 2011-11-10T19:48:48.143 に答える
0

あなたはこれについて少し間違った方法で考えています。メソッドがシートの終了を待つことができた場合、アプリのイベント ループがブロックされ、ユーザーが UI を操作できなくなります。アラートにを使用するrunModalと、アラートを処理するための新しい実行ループが作成されます。これが、アプリに対して他に何もできない理由です。シート オプションのポイントは、アラートが表示されている間、ユーザーが他のことを実行できるようにすることです。つまり、イベント処理を明示的に引き継ぐことはありません。

子ウィンドウを接続することで、シートを偽造することを検討できます。

于 2011-11-10T18:56:38.417 に答える
0

シートが削除されるまで(フリーズ = NO を設定) 、アプリでフリーズしたいものをすべてフリーズする(freeze = YES を設定)ブール値を設定することができます。 一般的なケースでは、メソッドをブロックする必要はありません。ユーザーが選択を行うまで、いくつかのことが起こらないようにするだけです。

たとえば、ジャイロスコープを使用するアプリがあります。ある動作とない動作があります。
したがって、ジャイロデータを使用して動作を適切なものにルーティングするメソッドで使用されるブール値があります。私の useGyro Boolean は次の場合 NO です: ユーザーがどの種類のハードウェア機能を有効にするかどうかを選択していて、ジャイロがデバイスで利用できない場合。

私が持っているmapViewでも同じことが言えます。ユーザーがシステムにアクセスしたい場合、ユーザーの場所を使用して動作をフリーズする瞬間があります。彼が選択したら、その bool 値を変更します。

于 2011-11-10T18:57:49.280 に答える