ページ

2010年3月15日月曜日

Keychain Services 調査 (14) コーディング #3 ログインシートの表示

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: Keychain Services 調査 (13) コーディング #2 パスワードを取得する(拒否した場合)

今回はログイン用の UI を用意する。UI は以前調査した時の Safari などのようにシートを使うことにする。
(参考)Cocoaの日々: Keychain Services 調査 (10) ID/パスワード入力例

シートの出し方はネットで探すとたくさん出てくる。
(参考)NSApplication


手順は簡単で、まず Interface Builder を使い、シートの UI を NSWindow として用意する。

後はこれを NSApplication のメソッドを使い表示するだけ。

-[beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo:] を使う。
Mac Dev Center: NSApplication Class Reference

実装はこんな感じ。
KeychainSample1AppDelegate.m
- (void)sheetDidEnd:(NSWindow *)sheet
 returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
 [authenticateWindow orderOut:nil];
 NSLog(@"returnCode=%d", returnCode);
}

-(IBAction)connect:(id)sender
{
 [NSApp beginSheet:authenticateWindow
    modalForWindow:window
  modalDelegate:self
    didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
    contextInfo:nil];
}

modalDelegate: を設定しておくとダイアログを閉じた時に didEndSelector: で定義したメソッドが呼び出される。ダイアログを閉じるには endSheet: または endSheet:returnCode: を使う。

-(IBAction)login:(id)sender
{
 [NSApp endSheet:authenticateWindow];
}

-(IBAction)cancel:(id)cancel
{
 [NSApp endSheet:authenticateWindow];
}

OK/Cancelの処理は、各ボタンのハンドラ(上記の例の場合 login: や cancel: )で行うか、endSheet:returnCode: でシートを閉じた後、コールバックされる delegate メソッド内でその returnCode: を見て行う。

Mac Dev Center 配布のサンプル ImageClient のコードを見るとこんな書き方をしていた。
ImageClient

- (IBAction)dismissAuthSheet:(id)sender {
    [[NSApplication sharedApplication] endSheet:authSheet
          returnCode: [(NSControl*)sender tag]];
}
InterfaceBuilderで確認すると Cancelは tag=0, OKは tag=1 となっていた。これを条件分岐に使う。
- (void)authSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {
    if (returnCode == NSOKButton) {
      :

NSOKButton は NSPanel.h でこう定義されている。
enum {
    NSOKButton    = 1,
    NSCancelButton   = 0
};

変わることは無いだろうけど、実際は自分で割り当てた値を使った方がいいだろう。


その他シートの注意点としては、シートを閉じるのは自分で行う必要があるところ。

[authenticateWindow orderOut:nil];



さて、実行してみよう。今回はシートを表示するだけ。