UITextFieldで指定したテンキー(UIKeyboardTypeNumberPad)に「DONE」ボタンを付ける方法

http://www.neoos.ch/news/46-development/54-uikeyboardtypenumberpad-and-the-missing-return-key

UITextFieldにはkeyboardTypeというプロパティがあり、下記のような記述でテンキーを指定できます。

textField.keyboardType = UIKeyboardTypeNumberPad;

だけど、このテンキーには通常のキーボード表示のときにあった「DONE」ボタンがないんです。これだと数値入力が終わったときに、キーボードを引っ込めるのに困ってしまいますね。そこで見つけたのが上記サイト。力技で「DONE」ボタンを追加する方法が紹介してあり大変参考になりました。

- (void)keyboardWillShow:(NSNotification *)note {  
    // create custom button
    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
    doneButton.frame = CGRectMake(0, 163, 106, 53);
    doneButton.adjustsImageWhenHighlighted = NO;
    [doneButton setImage:[UIImage imageNamed:@"DoneUp.png"] forState:UIControlStateNormal];
    [doneButton setImage:[UIImage imageNamed:@"DoneDown.png"] forState:UIControlStateHighlighted];
    [doneButton addTarget:self action:@selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
	
    // locate keyboard view
    UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
    UIView* keyboard;
    for(int i=0; i<[tempWindow.subviews count]; i++) {
        keyboard = [tempWindow.subviews objectAtIndex:i];
        // keyboard view found; add the custom button to it
        if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
            [keyboard addSubview:doneButton];
    }
}

すなわち、doneButtonという名のUIButtonを生成して、これをキーボードのviewの上にsubviewとして追加するのです。なるほど、頭の良い人がいるものですね。「DONE」ボタンはNormal時用に「DoneUp.png」、highlighted時用にに「DoneDown.png」という名前でプロジェクトの「Resources」フォルダに登録しておいてください。画像のサイズは106*53pixです。
さて、では上記メソッドをトリガーするのは、もちろんキーボードが表示されたときがいいですね。

- (void)viewDidLoad {
	[[NSNotificationCenter defaultCenter] addObserver:self
		selector:@selector(keyboardWillShow:)
		name:UIKeyboardWillShowNotification
		object:nil];
}	

これをviewDidLoadメソッドの中に書いておきます。するとNSNotificationCenterがキーボードが表示されるタイミング(UIKeyboardWillShowNotification)を監視してくれて、表示されたときkeyboardWillShow:メソッドをトリガーしてくれます。

- (void)dealloc {
	[[NSNotificationCenter defaultCenter] removeObserver:nil];	
}

解放もお忘れなく。

あとは、実際に「DONE」ボタンをクリックしたときにトリガーされるメソッドを書いておしまい。

- (void)doneButton:(id)sender {
	[activeField resignFirstResponder];
}

入力している(アクティブな)textFieldを特定するために格納しておいたactiveFieldというポインタにresignFirstResponderメソッドを呼び出すことでキーボードが無事格納されます。
これについては、こっちの記事を参照してください。
http://d.hatena.ne.jp/manmarina/20100619/1276923171