キーボードを閉じる簡単な方法?


377

テーブルの多くのセルにかなりの数のコントロールが散在しています。すべてのコントロールをループして最初のレスポンダーとしてすべてを辞任せずにキーボードを非表示にする簡単な方法があるかどうか疑問に思いました。私は質問だと思います。現在のファーストレスポンダをキーボードに取得するにはどうすればよいですか?


この質問への素敵な補完:stackoverflow.com/questions/1490573/...
ericsoco

以下のすべての回答に対する警告。KBを辞任した直後にセグエを実行すると、KBは孤立し、破棄できません。textFieldShouldReturnメソッドでKBを閉じる必要があります。
gjpc 2014

26
グローバルキーボードによる正しい方法での解任:[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
Yerk、2015年

私はこのビデオが役立つピンクストーン.co.uk /…を見つけました 。多分それは他の人を助けることができます。
enthusiasticgeek

回答:


797

試してください:

[self.view endEditing:YES];

1
これは動作するようです(ios4.1でテスト済み)。iOS 3.2以降でのみ利用できます。これが実際に動作することが保証されているのか、それとも動作することが文書化されていない方法でAPIを呼び出すことによる保証されていない副作用であるのかはわかりません。
JosephH

3
これは私にとっては完全に機能し、この質問に対する他のいくつかの回答よりも確かに望ましい方法です。ドキュメントによると、iOS 2.0以降で利用可能です。
antyawn 2010

8
ドキュメントが言うように:「このメソッドは、現在最初のレスポンダーであるテキストフィールドの現在のビューとそのサブビュー階層を調べます。見つかった場合、最初のレスポンダーとして辞任するようにテキストフィールドに要求します。forceパラメーターが設定されている場合はい、テキストフィールドが要求されることはありません。辞任を余儀なくされます。」-つまり、これはIMOが元の質問に対する正しい答えです(ユースケース:数百万のフィールドを持つフォームがあります-10かそこらで、キーボードを閉じる必要があります)。
joshis

14
答えは間違っていませんが、少し間違っていますが、実際には次のようになります[self.view endEditing:YES];。Objective-CではBOOL値がYES / NOであるためです。
chrisben 2013年

24
chrisben:YES / NO、TRUE / FALSE、0/1を使用できます。
Michael Superczynski 2013年

126

現在編集中のビューに、最初のレスポンダのステータスを強制的に辞任させることができます[view endEditing:YES]。これによりキーボードが非表示になります。

とは異なり-[UIResponder resignFirstResponder]-[UIView endEditing:]はサブビューを検索して、現在の最初のレスポンダを見つけます。したがって、それをトップレベルのビュー(例:self.viewUIViewController)に送信すると、正しい動作をします。

(この回答には以前、他のいくつかのソリューションが含まれていましたが、これらも機能しましたが、必要以上に複雑でした。混乱を避けるために、それらを削除しました。)


ただし、これはコンポーネントがfirstResponderになるのをブロックするだけで、要素から現在のfirstResponderステータスを削除しません。
Kendall Helmstetter Gelner、

ファーストレスポンダをどこかに保存するために、becomeFirstResponderをオーバーライドすることで、後でアクセス(この場合は辞任)できるようになりました。基本的な問題は、Cocoa Touchがウィンドウに質問したり、ファーストレスポンダを確認したりできないことです。
ニコラスライリー

+ 1becomeFirstResponderを追加すると、他のUITextFieldのタップで発生していた問題が解決しました。
ジェイソンジョージ

3
これは時代遅れです。[self.view endEditing:YES];答えは優れています。
ftvs 2012年

1
これは時代遅れではなく、この答えはどのように[UIView endediting:]機能するかを正確に説明しています。私が開発したアプリの1つで、UINavigationViewControllerに検索ボックスが追加されました。ビューコントローラー[self.view endEditing:YES]としてを呼び出すだけでselfは機能しません。代わりに、検索ボックスが追加されたビュースコープでこのメソッドを直接呼び出しました。例:[self.mySearchBoxView endEditing:YES]
JanCássio2015

92

nilターゲットアクションをアプリケーションに送信できます。これは、どのビューが現在ファーストレスポンダステータスであるかを気にする必要なく、いつでもファーストレスポンダを辞任します。

Objective-C:

[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

Swift 3.0:

UIApplication.shared.sendAction(#selector(resignFirstResponder), to: nil, from: nil, for: nil)

Nilを対象とするアクションは、Mac OS Xではメニューコマンドに共通ですが、iOSではこれらを使用します。


14
ページ全体の最適なソリューション。
レオナタン

iOSアプリのどこからでもキーボードを取り除くのに最適な方法です。
ベンシンクレア

iOS8でも引き続き動作します。私のアプリケーションでは、サイドバーメニューがあり、「中央」のビューコントローラーにキーボードが表示されることがあります。サイドバーメニューが表示される場合は、キーボードを閉じます。そこで、このコードをサイドバーメニューのClassのviewWillAppearメソッドに追加しました。
ジェンイブ

1
iOS 9でも引き続き機能します。テキストフィールドのフォーカスをグローバルに辞任し、キーボードを閉じるのに最適な方法です。
bmjohns

そして、この特定のコメントの続きを続けるには... iOS 10でも引き続き機能します。:-)
Traveling Man

56

正直なところ、私はここで提案されているソリューションのどれにも夢中ではありません。TapGestureRecognizerを使用する良い方法を見つけました。問題の核心に到達すると思います。キーボード以外の何かをクリックすると、キーボードを閉じます。

  1. viewDidLoadで、キーボード通知を受信して​​UITapGestureRecognizerを作成するように登録します。

    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    
    [nc addObserver:self selector:@selector(keyboardWillShow:) name:
    UIKeyboardWillShowNotification object:nil];
    
    [nc addObserver:self selector:@selector(keyboardWillHide:) name:
    UIKeyboardWillHideNotification object:nil];
    
    tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
    action:@selector(didTapAnywhere:)];
  2. キーボードの表示/非表示レスポンダを追加します。そこで、タップするとキーボードを閉じるはずのTapGestureRecognizerをUIViewに追加して削除します。注:すべてのサブビューまたはコントロールに追加する必要はありません。

    -(void) keyboardWillShow:(NSNotification *) note {
        [self.view addGestureRecognizer:tapRecognizer];
    }
    
    -(void) keyboardWillHide:(NSNotification *) note
    {
        [self.view removeGestureRecognizer:tapRecognizer];
    }
  3. TapGestureRecognizerは、タップを受け取ると関数を呼び出し、次のようにキーボードを閉じることができます。

    -(void)didTapAnywhere: (UITapGestureRecognizer*) recognizer {    
        [textField resignFirstResponder];
    }

このソリューションの優れた点は、スワイプではなくタップのみをフィルタリングすることです。したがって、キーボードの上にコンテンツをスクロールしている場合でも、スワイプはスクロールし、キーボードは表示されたままになります。キーボードがなくなった後にジェスチャーレコグナイザーを削除することで、ビューの今後のタップは通常どおり処理されます。


@implementationに@property(assign)UITapGestureRecognizer * tapRecognizer;を追加しました。変更されたself.tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapAnywhere :)];
トッド教授、2011

私は同様のことをやろうとしているのですが、タップでコールバックされません。好奇心が強い:なぜあなたの財産は「譲渡」されるのですか?
TahoeWolverine、2011

プラス1、さらにこれはiOSのデフォルトの動作です。または、少なくとも、閉じるボタンを切り替える簡単な方法を追加します。
Shaunti Fondrisi

24

これは、1つの場所にコードを追加することによりreturn任意のテキストフィールドでヒットしたときにキーボードが表示されないようにするためのソリューションです(各テキストフィールドにハンドラーを追加する必要はありません)。


このシナリオを検討してください:

私はviewcontroller2つのテキストフィールド(ユーザー名とパスワード)を持っています。およびviewcontroller実装UITextFieldDelegateプロトコル

私はviewDidLoadでこれを行います

- (void)viewDidLoad 
{
    [super viewDidLoad];

    username.delegate = self;
    password.delegate = self;
}

そしてviewcontrollerはオプションのメソッドを次のように実装します

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}

そして、あなたがいるテキストフィールドに関係なく、私がreturnキーボードを押すとすぐに、それは却下されます!

あなたの場合、テキストフィールドのすべてのデリゲートをselfに設定して実装する限り、同じことが機能します textFieldShouldReturn


さて、私はすでに問題を解決しましたが、私の場合、自分でキーボードを(コードで)消したいと思っていました。
Seventoes 2009

1
サイドバーメニューが表示されようとしているときなど、「戻る」を押さずにキーボードを閉じたい場合があります
Peter Johnson

この回答は、「return」を押すことが受け入れ可能なソリューションである場合にのみ関連することを明確にするために編集されました。[私の場合、ユーザーが編集中のフィールドの外側をタップしたときにキーボードも非表示にしたかった。この答えはそれでは役に立ちません。]
ToolmakerSteve

14

より良いアプローチは、何かを「盗む」ファーストレスポンダステータスを持つことです。

UIApplicationはUIResponderのサブクラスなので、次のことを試すことができます。

[[UIApplication sharedApplication] becomeFirstResponder]
[[UIApplication sharedApplication] resignFirstResponder]

それが失敗した場合は、サイズがゼロのフレームで新しいUITextFieldを作成し、それをビューのどこかに追加して、同様のことを行います(その後、辞任します)。


1
UIApplicationトリックは機能しません(少なくともシミュレータではクラッシュします)が、サイズが0のUITextFieldは必要ありません。ランダムなフィールドを選択してこれを実行するだけです。NSResponderのBecomeFirstResponderは通知のみのメソッドですが、UIResponderはそうではありません(実際にはデザインは悪いです)。
ニコラスライリー

1
あ、ありがとう!UIApplicationで呼び出すとクラッシュしますが、サイズがゼロのUITextFieldは適切に機能し、以前のフィールドを取得する必要はありません。
Seventoes 2009

公式に完全に文書化された文書化された方法がある場合、なぜこれを行うのでしょうか?
Maciej Swic 2013

2
彼らはそうはしないでしょう。当時はあまり知られていませんでした(私の回答は2009年からでしたが、もう1つの回答は2010年の1年以上後です)。しかし、私は後世のためにそれを残します。
Kendall Helmstetter Gelner 2013

8

これをいくつかのユーティリティクラスに入れます。

+ (void)dismissKeyboard {
    [self globalResignFirstResponder];
}

+ (void) globalResignFirstResponder {
    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    for (UIView * view in [window subviews]){
        [self globalResignFirstResponderRec:view];
    }
}

+ (void) globalResignFirstResponderRec:(UIView*) view {
    if ([view respondsToSelector:@selector(resignFirstResponder)]){
        [view resignFirstResponder];
    }
    for (UIView * subview in [view subviews]){
        [self globalResignFirstResponderRec:subview];
    }
}

1
これは私が探していたものです!
aslisabanci 2011

完璧です。globalResignFirstResponderRecメソッドがまったく必要ない場合を除いて、代わりに[view endEditing:YES]を呼び出します。同じことをします。
n13

うん!最終的な解決策!私は多くの方法を試しました、これだけが私のために働きます!どうもありがとうございました!
douyw 2016年

6

@Nicholas Riley&@Kendall Helmstetter Geln&@cannyboy:

絶対に素晴らしい!

ありがとうございました。

あなたのアドバイスとこのスレッドの他の人のアドバイスを考慮して、これは私がやったことです:

使用時の外観:

[[self appDelegate] dismissKeyboard]; (注:NSObjectへの追加としてappDelegateを追加したので、どこでもどこでも使用できます)

ボンネットの下の様子:

- (void)dismissKeyboard 
{
    UITextField *tempTextField = [[[UITextField alloc] initWithFrame:CGRectZero] autorelease];
    tempTextField.enabled = NO;
    [myRootViewController.view addSubview:tempTextField];
    [tempTextField becomeFirstResponder];
    [tempTextField resignFirstResponder];
    [tempTextField removeFromSuperview];
}

編集

含まれた私の答えへの修正tempTextField.enabled = NO;。テキストフィールドを無効にするUIKeyboardWillShowNotificationUIKeyboardWillHideNotification、アプリ全体でこれらの通知に依存している場合にキーボード通知が送信されなくなります。


うまくいくかどうかはわかりませんが、スマートで簡単な方法のようです。
2013

5

ユーザーがUITextFieldまたはキーボードの外側の画面上の任意の場所に触れたときにiOSでキーボードを閉じる方法に関する簡単なヒント。iOSキーボードがどれだけのスペースを取ることができるかを考えると、ユーザーがキーボードを閉じるための簡単で直感的な方法を持つことは理にかなっています。

ここにリンクがあります


すごい!AppDelegateに追加すると、すべての関連ビューで機能します。
Jiulong Zhao

5

これは非常に複雑な答えがたくさんあります。おそらくこれはiOSのドキュメントで簡単に見つけることができないためです。ジョセフはそれを真上に持っていました:

[[view window] endEditing:YES];

4

Meagarの答えよりもさらに単純

上書きする touchesBegan:withEvent:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [textField resignFirstResponder];`
}

これはdismiss the keyboard、のどこかにタッチすると発生しますbackground


3

これが私のコードで使用するものです。それは魅力のように機能します!

yourviewcontroller.hに以下を追加します。

@property (nonatomic) UITapGestureRecognizer *tapRecognizer;

.mファイルで、これをViewDidLoad関数に追加します。

- (void)viewDidLoad {
    //Keyboard stuff
    tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapAnywhere:)];
    tapRecognizer.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tapRecognizer];
}

また、この関数を.mファイルに追加します。

- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
    [self.view endEditing:YES];
}

ありがとう!ただし、関数の名前を「didTapAnywhere」に変更するか、ジェスチャ認識機能を「handleSingleTap」に変更する必要があります;-)
Matthijs

2

ビューコントローラーのヘッダーファイル<UITextFieldDelegate>で、コントローラーのインターフェイスの定義に追加して、UITextFieldデリゲートプロトコルに準拠するようにします...

@interface someViewController : UIViewController <UITextFieldDelegate>

...コントローラーの実装ファイル(.m)に次のメソッドを追加するか、すでにviewDidLoadメソッドがある場合はその中にコードを追加します...

- (void)viewDidLoad
{
    // Do any additional setup after loading the view, typically from a nib.
    self.yourTextBox.delegate = self;
}

...次に、yourTextBoxを実際のテキストフィールドにリンクします。

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField 
{
    if (theTextField == yourTextBox) {
        [theTextField resignFirstResponder];
    }
    return YES;
}

2

あなたはendEditing:のサブクラスである作業ウィンドウに送る必要がありますUIView

[[UIApplication sharedApplication].windows.firstObject endEditing:NO];

私はあなたが代わりにYESを意味していたに
違い

2

UITableViewとUIScrollViewからキーボードを閉じる最良の方法は次のとおりです。

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag

2

Swift 3では次のことができます

UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)

1

ジェレミーの答えは私にはあまりうまくいきませんでした。なぜなら、モーダルダイアログの上にタブビューのナビゲーションスタックがあったからです。現在、以下を使用していますが、問題なく機能しますが、走行距離が異なる場合があります。

 // dismiss keyboard (mostly macro)
[[UIApplication sharedApplication].delegate dismissKeyboard]; // call this in your to app dismiss the keybaord

// --- dismiss keyboard (in indexAppDelegate.h) (mostly macro)
- (void)dismissKeyboard;

// --- dismiss keyboard (in indexAppDelegate.m) (mostly macro)
// do this from anywhere to dismiss the keybard
- (void)dismissKeyboard {    // from: http://stackoverflow.com/questions/741185/easy-way-to-dismiss-keyboard

    UITextField *tempTextField = [[UITextField alloc] initWithFrame:CGRectZero];

    UIViewController *myRootViewController = <#viewController#>; // for simple apps (INPUT: viewController is whatever your root controller is called.  Probably is a way to determine this progragrammatically)
    UIViewController *uivc;
    if (myRootViewController.navigationController != nil) { // for when there is a nav stack
        uivc = myRootViewController.navigationController;
    } else {
        uivc = myRootViewController;
    }

    if (uivc.modalViewController != nil) { // for when there is something modal
        uivc = uivc.modalViewController;
    } 

    [uivc.view  addSubview:tempTextField];

    [tempTextField becomeFirstResponder];
    [tempTextField resignFirstResponder];
    [tempTextField removeFromSuperview];
    [tempTextField release];

}

うーん-なぜ反対票か テスト済みのコードを使用して、別の回答で特定の現実世界の欠点に対処しました。私は賛成票がないことを理解できますが、否定的な領域に私を投票することは本当に落胆です。上記の答えが他の誰かの役に立つことを願っています。
JJ Rohrer、2011年

1

これを機能させるために、UIViewController disablesAutomaticKeyboardDismissalをオーバーライドする必要がある場合もあります。UINavigationControllerがある場合は、これを行う必要があります。


1

テキストフィールドをサブクラス化し...テキストビューも

サブクラスにこのコードを入れます。

-(void)conformsToKeyboardDismissNotification{

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissKeyBoard) name:KEYBOARD_DISMISS object:nil];
}

-(void)deConformsToKeyboardDismissNotification{

    [[NSNotificationCenter defaultCenter] removeObserver:self name:KEYBOARD_DISMISS object:nil];
}

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

テキストフィールドデリゲート(テキストビューデリゲートと同様)

-(void)textFieldDidBeginEditing:(JCPTextField *)textField{
     [textField conformsToKeyboardDismissNotification];
}


- (void)textFieldDidEndEditing:(JCPTextField *)textField{
    [textField deConformsToKeyboardDismissNotification];
}

すべて設定しました。コード内のどこからでも通知を投稿してください。それはキーボードを辞任します。


1

そして迅速に

UIApplication.sharedApplication().sendAction("resignFirstResponder", to: nil, from: nil, forEvent: nil)

ファーストレスポンダーのしくみがわかりません。これはどこに置けばよいですか。私のView Controllerまたはデリゲートで?
Shayan C 2016

関係ありません。どこにでも置くことができます。ieボタンアクション
Eike

1

キーボードがポップアップした後でキーボードを閉じるには、2つのケースがあります。

  1. UITextFieldがUIScrollView内にあるとき

  2. UITextFieldがUIScrollViewの外にあるとき

2.UITextFieldがUIScrollViewの外側にある場合、UIViewControllerサブクラスのメソッドをオーバーライドします

すべてのUITextViewのデリゲート追加する必要があります

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [self.view endEditing:YES];
}
  1. ではスクロールビュー、外側をタップすると、いずれかのイベントが発生しませんので、その場合には、使用をタップジェスチャー認識装置を、ドラッグ&ドロップUITapGestureをスクロールビューのためにと、そのためのIBActionを作成します

IBActionを作成するには、Ctrlキーを押しながらUITapGestureをクリックし、それをビューコントローラーの.hファイルにドラッグします。

ここでは、アクション名としてtappedEventという名前を付けています

- (IBAction)tappedEvent:(id)sender {
      [self.view endEditing:YES];  }

与えられた情報は次のリンクから導き出されました。詳細については参照するか、情報について理解できない場合は私に連絡してください。

http://samwize.com/2014/03/27/dismiss-keyboard-when-tap-outside-a-uitextfield-slash-uitextview/


0

プライベートAPI呼び出しを使用せずにプログラムでキーボードを閉じる「グローバルな」方法はないのが嫌いです。多くの場合、最初のレスポンダーであるオブジェクトを知らずに、プログラムでキーボードを閉じる必要があります。私はselfObjective-CランタイムAPIを使用してを検査し、そのすべてのプロパティを列挙し、タイプUITextFieldであるものを引き出し、それらを送信することに頼りましたresignFirstResponderメッセージ。

これを行うのはそれほど難しいことではありません...


0

それはきれいではありませんが、レスポンダーが何であるかわからないときにfirstResponderを辞任する方法:

IBで、またはプログラムで、UITextFieldを作成します。非表示にします。IBで作成した場合は、コードにリンクします。次に、キーボードを非表示にする場合は、レスポンダを非表示のテキストフィールドに切り替え、すぐに再署名します。

  [self.invisibleField becomeFirstResponder];
  [self.invisibleField resignFirstResponder];

0

サブビューを再帰的に反復し、すべてのUITextFieldの配列を格納してから、それらをループしてすべてに再署名できます。

特に多くのサブビューがある場合は特に優れた解決策ではありませんが、単純なアプリの場合はうまくいくはずです。

私はこれをはるかに複雑ですが、はるかにパフォーマンスの高い方法で解決しましたが、アプリのアニメーションエンジンにシングルトン/マネージャーを使用し、テキストフィールドがレスポンダーになるたびに、それをstaticに割り当てて、他の特定のイベントに基づいて一掃された(辞任)...段落で説明することはほとんど不可能です。

この質問を見つけた後、私が自分のアプリについてこれを検討するのに10分しかかかりませんでした。


この数か月前に解決しました;)フォーカスのあるアクティブフィールドを保存し、それを使用するだけになりました。
Seventoes

0

最近使用する必要があるもう少し堅牢な方法:

- (void) dismissKeyboard {
    NSArray *windows = [UIApplication sharedApplication].windows;

    for(UIWindow *window in windows) [window endEditing:true];

    //  Or if you're only working with one UIWindow:

    [[UIApplication sharedApplication].keyWindow endEditing:true];
}

他の「グローバル」メソッドの一部が機能しないことがわかりました(たとえば、UIWebViewWKWebView辞退を拒否しました)。


0

タップジェスチャーレコグナイザーをビューに追加します。

あなたの.mファイルは次のようになります

    - (IBAction)hideKeyboardGesture:(id)sender {
    NSArray *windows = [UIApplication sharedApplication].windows;
    for(UIWindow *window in windows) [window endEditing:true];
    [[UIApplication sharedApplication].keyWindow endEditing:true];
}

それは私のために働いた


0

はい、endEditingが最良のオプションです。また、iOW 7.0以降UIScrollView、スクロールビューの操作時にキーボードを非表示にする優れた機能があります。これを実現するために、のkeyboardDismissModeプロパティを設定できますUIScrollView

キーボードの非表示モードを次のように設定します。

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag

他のタイプはほとんどありません。このアップルのドキュメントをご覧ください



0

最も簡単な方法は、メソッドを呼び出すことです

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    if(![txtfld resignFirstResponder])
    {
        [txtfld resignFirstResponder];
    }
    else
    {

    }
    [super touchesBegan:touches withEvent:event];
}

そこに 'if'は必要ありません。resignFirstResponderはとにかくそれを行います。多分あなたは-(BOOL)canResignFirstResponderを意味しましたか?
Seventoes 2010

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.