UITextFieldを編集するとき、キーボードをどのように閉じますか


181

キーボードを閉じたいときに最初のレスポンダーを辞任するようにUITextFieldに指示する必要があることはわかっていますが、ユーザーがキーボードの「Done」キーを押したときを知る方法がわかりません。監視できる通知はありますか?


2
[self.view endEditing:YES]; 触れて始めたデリゲートは最高のソリューションです
Zar E Ahmer 14年

回答:


351

私はのデリゲートを設定しUITextField、私にViewControllerクラス。

そのクラスで、このメソッドを次のように実装しました。

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

上記の例を参照してください... IntefaceBuilderを使用して、コントローラーとして使用しているもののアクションにワイヤリングします...ユーザーがテキスト入力システムを終了する(完了を押す)と、これが呼び出されます...
Jason Coco

2
これらのどちらでも機能します。テキストフィールドは、ユーザーがReturn( "Done"など)キーを押すとアクションを送信し、デリゲート-textFieldShouldReturn:も送信します。
Noah Witherspoon

ところで-これはUISearchBarでも機能します。たとえば、コードにメンバーIBOutlet searchBarTusbがありました。「リターンキー」(UIReturnKeySearch)がクリックされたとき、-(void)searchBarSearchButtonClicked:のように、ステートメント[searchBarTusb resignFirstResponder]を挿入しました。また、「リターンキー」はInterface Builderを使用してNIBで設定されていることに注意してください。
mobibob

なぜNO代わりに戻るのYESですか?
Iulian Onofrei

@IulianOnofrei戻るボタンのデフォルトの動作は、改行を追加してキーボードを画面上に維持することです。返すことによって、NOテキストに改行を追加しません。
kubi

47

テキストフィールドのDidEndOnExitイベントをInterfaceBuilderのアクション(IBAction)に接続すると、ユーザーがキーボードを閉じると(Returnキーで)メッセージが送信され、送信者はイベントを発生させたUITextFieldへの参照になります。

例えば:

-(IBAction)userDoneEnteringText:(id)sender
{
    UITextField theField = (UITextField*)sender;
    // do whatever you want with this text field
}

次に、InterfaceBuilderで、テキストフィールドのDidEndOnExitイベントを、コントローラー(またはUIからイベントをリンクするために使用しているもの)のこのアクションにリンクします。ユーザーがテキストを入力してテキストフィールドを閉じると、コントローラーにこのメッセージが送信されます。


うまくいくように見える唯一のイベントはtextFieldDidEndEditingです。これは、UITextFieldが最初のレスポンダステータスを辞任した後にのみ送信されることを示しています。ファーストレスポンダのステータスを辞任する必要がある場合、どうすればわかりますか?
kubi

用語については申し訳ありません...実際の通知(イベント)ではありません...簡単な例と説明で回答を編集しますので、それを参照してください:)
Jason Coco

1
この答えを明確にするために、リターンキーを押すと、textFieldが「Did End On Exit」イベントを送信するため、コントローラーにリンクする必要があります。この方法は、上で概説した方法よりも簡単だと思います。
kubi

2
この回答を編集して、ワイヤリングするイベントを記載してください。これは、デリゲートを設定するより明らかに優れています。
Dan Rosenstark、2010

1
この回答を賛成したいのですが、DidEndOnExitイベントについて言及するまではできません。OPが編集しない場合は、編集権限を持つ誰かが変更を加えてください。
James Hart

32

コントローラでメソッドを作成することもできます

 -(IBAction)editingEnded:(id)sender{
    [sender resignFirstResponder]; 
}

次に、IBのConnection Inspectorでイベント「Did End On Exit」に接続します。


1
これはほとんど正しくないか、少なくともポイントを逃しています。DidEndOnExitイベントに登録することで、を呼び出す必要がなくなりますresignFirstResponder。これは、シンボリックブレークポイントをに置くことでテストできます[UIResponder resignFirstResponder]。resignFirstResponderを呼び出さなくても、システムによって呼び出されることに注意してください。:これは、マット・ニューバーグの優れた著書(S)で説明されてapeth.com/iOSBook/...
クリス・コノバー

19

クビ、ありがとう。コードが機能しました。あなたが設定する必要が言うようにだけは、(のような初心者のために)明示的に指定するUITextFieldのにdelegateテキストフィールドが存在するのViewControllerに等しくなるように。好きな場所でこれを行うことができます。私はviewDidLoad方法を選びました。

- (void)viewDidLoad 
{
    // sets the textField delegates to equal this viewController ... this allows for the keyboard to disappear after pressing done
    daTextField.delegate = self;
}

ストーリーボードまたはNIBにテキストフィールドを追加した場合は、delegateそこにもテキストフィールドを設定できます。上で示したように、これをプログラムで行う必要はありません。どちらの方法でも問題なく機能します。
Rob

18

コードなしでキーボードを自動的に閉じる動作を実現するための秘訣を次に示します。nibで、IDインスペクターのFirst Responderプロキシオブジェクトを編集し、新しいFirst Responderアクションを追加します。それを呼びましょうdummy:。次に、テキストフィールドのDid End on Exitイベントをdummy:First Responderプロキシオブジェクトのアクションにフックします。それでおしまい!テキストフィールドのDid End on Exitイベントにアクションとターゲットのペアがあるため、ユーザーがReturnキーをタップすると、テキストフィールドは自動的にキーボードを閉じます。また、レスポンダーチェーンに送信されたメッセージのハンドラーを見つけられないというペナルティがないため、dummy:どこにも実装がなくてもアプリはクラッシュしません。


@matt巻き戻しセグエを追加し、didEndOnExitイベントを接続すると、Returnキーを押すと巻き戻しセグエがトリガーされることがわかりました。イベント接続がないと、セグエはトリガーされません。素晴らしいけどね?備考はありますか?ところで:私はあなたのSwift(終了)とiOS10(第6章)の本を持っています。彼らは私をものすごく助けてくれました!
Verticon 2017年

@Verticonの質問と回答はセグエとは何の関係もないため、問題を理解できません... :(これは純粋にキーボードの解任に関するものです
マット

@mattすみません。1)UITextFieldのリターンキーの処理方法を処理しているときにこのスレッドに出会ったため、私は後押ししました。2)それはあなたと交流する機会でした(da本ではthx)。「問題」はありません。なぜ/どのように機能するのかについて私の側で理解が不足しているだけです。
Verticon 2017年

@Verticonお役に立てなかったことをお詫び申し上げます。役立つ情報がありましたら、詳細情報(デモプロジェクト?)を使用して新しい質問を自由に作成し、メッセージを送ってください。
マット2017年

@mattありがとう、stackoverflow.com
questions / 47289747 /…

11

追加するだけ

[textField endEditing:YES];

キーボードを無効にしてピッカービューを表示する場所。


10

Swiftでは、コントローラーにIBActionを記述し、テキストフィールドのDid End On Exitイベントをそのアクションに設定できます。

@IBAction func returnPressed(sender: UITextField) {
    self.view.endEditing(true)
}

5

Swift 4.2 そしてそれは100%機能します

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        self.textField.delegate = self

    }

    // hide key board when the user touches outside keyboard

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }

    // user presses return key

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}

4

あなたも使うことができます

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
  {

   [self.yourTextField resignFirstResponder];

  }

あなたが多くのUitextfieldを持っているなら最高のもの:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
 {    
     [self.view endEditing:YES];
 }

2

これが機能するために私がしなければならなかったことは次のとおりです。キーボード用のテンキーを持っている人(または完了ボタンのない他の人)には必要だと思います。

  1. ViewControllerのUIViewをUIControlに変更しました。
  2. という関数を作成しました

    -(IBAction)backgroundIsTapped:(id)sender

これも.hファイルで定義されています。

この後、Interface BuilderでViewControllerの「タッチダウン」ビットにリンクしました。

「バックグラウンドがタップされる」関数には、次のように配置します。

    [answerField resignFirstResponder];

「answerField」をキーボードを削除するUITextFieldの名前に変更することを忘れないでください(明らかに、UITextFieldが以下のように定義されていることを確認してください:)

    IBOutlet UITextField * <nameoftextfieldhere>;

このトピックはおそらくかなり前に消滅したことを知っています...しかし、これがどこかで誰かを助けることを願っています!


..しかし、ユーザーが別のコントロールをタップした場合、うまく機能しません。
ragnarius 14

2

メソッド「textFieldShouldReturn」がDONEキーを押したテキストフィールドオブジェクトを提供することに気づくでしょう。タグを設定すると、そのテキストフィールドをオンにすることができます。または、オブジェクトのポインターを追跡して、作成者が保存したメンバー値と比較することもできます。

私のアプローチは、自習のためのこのようなものです:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    bool fDidResign = [textField resignFirstResponder];

    NSLog(@"%s: did %resign the keyboard", __FUNCTION__, fDidResign ? @"" : @"not ");

    return fDidResign;
}

その間、私は辞任を否定する「検証」テストを続けます。これは説明のためだけなので、ユーザーがNOと入力した場合は!フィールドに、それは却下されません。動作は私が望んだとおりでしたが、出力のシーケンスは期待したとおりではありませんでした。

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    if( [[textField text] isEqualToString:@"NO!"] ) {
        NSLog(@"%@", textField.text);
        return NO;
    } else {
        return YES;
    }
}

以下は、この拒否のNSLog出力と、それに続く承認です。あなたは私が辞任の結果を返していることに気づくでしょうが、私は発信者に報告するために私にFALSEを返すと思っていましたか?!それ以外には、必要な動作があります。

13.313 StudyKbd [109:207]-[StudyKbdViewController textFieldShouldReturn:]
13.320 StudyKbd [109:207]-[StudyKbdViewController textFieldShouldEndEditing:]
13.327 StudyKbd [109:207]いいえ!
13.333 StudyKbd [109:207]-[StudyKbdViewController textFieldShouldReturn:]:キーボードを辞任しました
59.891 StudyKbd [109:207]-[StudyKbdViewController textFieldShouldReturn:]
59.897 StudyKbd [109:207]-[StudyKbdViewController textFieldShouldEndEditing:]
59.917 StudyKbd [109:207]-[StudyKbdViewController doneEditText]:いいえ
59.928 StudyKbd [109:207]-[StudyKbdViewController textFieldShouldReturn:]:キーボードを辞任しました

1
uについて説明できます。両方のケースでNOまたはYESを返す場合、同じことが発生するため、textFieldShouldReturnデリゲートメソッドでyesを返す必要性は何
ですか

1

リターンキーまたはバックグラウンドでのタッチでエディションを終了するための非常にクリーンな方法を次に示します。

Interface Builderで、フィールドをクラスUIFormViewのビューに埋め込みます。

このクラスは何ですか?

  • 自動的にフィールドデリゲートとして自分自身をアタッチします(nibから起動されるか、手動で追加されます)
  • 現在編集されているフィールドの参照を保持する
  • 戻るときにキーボードを閉じるか、バックグラウンドでタッチします

ここにコードがあります:

インターフェース

#import <UIKit/UIKit.h>

@interface UIFormView : UIView<UITextFieldDelegate>

-(BOOL)textFieldValueIsValid:(UITextField*)textField;
-(void)endEdit;

@end

実装

#import "UIFormView.h"

@implementation UIFormView
{
    UITextField* currentEditingTextField;
}

// Automatically register fields

-(void)addSubview:(UIView *)view
{
    [super addSubview:view];
    if ([view isKindOfClass:[UITextField class]]) {
        if ( ![(UITextField*)view delegate] ) [(UITextField*)view setDelegate:self];
    }
}

// UITextField Protocol

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    currentEditingTextField = textField;
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
    currentEditingTextField = NULL;
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self endEdit];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    if ([self textFieldValueIsValid:textField]) {
        [self endEdit];
        return YES;
    } else {
        return NO;
    }
}

// Own functions

-(void)endEdit
{
    if (currentEditingTextField) {
        [currentEditingTextField endEditing:YES];
        currentEditingTextField = NULL;
    }
}


// Override this in your subclass to handle eventual values that may prevent validation.

-(BOOL)textFieldValueIsValid:(UITextField*)textField
{
    return YES;
}

@end
  • フォームをサブクラス化してtextFieldValueIsValid:メソッドをオーバーライドすることにより 、指定されたフィールドの値が正しくない場合に、エディションの終了を回避できます。

  • Interface Builderでフィールドにデリゲートが設定されている場合、フォームはそれを変更しません。別のデリゲートを特定のフィールドに設定する理由は多くありませんが、なぜ…

このフォームビュークラスを改善するには多くの方法があります-デリゲートのアタッチ、レイアウトの実行、キーボードがフィールドをカバーするときの処理(currentEditingTextFieldフレームを使用)、次のフィールドの編集を自動的に開始、...

私は個人的にそれを自分のフレームワークに保持し、機能を追加するために常にサブクラス化します。これは、「現状のまま」で非常にしばしば役立ちます。

お役に立てば幸いです。乾杯


1
役立つクラス。小さな点の1つは、独自のクラスの先頭に「UI」を付けないことです。Objective-Cでは、独自のプレフィックス( "TL"?)を使用する必要があります。Swiftでは、何も使用しないでください。
kubi

@kubiに感謝します。そのとおり。それは、MooseFactoryのような私のフレームワークのMFです;)
Moose

1

UIViewControllerでのすべての編集が必要な場合は、使用できます。

[[self view]endEditing:YES];

特定のUITextFieldキーボードを非表示にする場合は、非表示にしてください。

1. viewcontroller.hにデリゲートを追加する

<UITextFieldDelegate>
  1. 委任をテキストフィールドにできないようにします。

    self.yourTextField.delegate = self;

  2. このメソッドをビューコントローラーに追加します。

    -(BOOL)textFieldShouldEndEditing:(UITextField *)textField {[textField resignFirstResponder]; YESを返す;}


1

Swift 3でUITextFieldのデリゲートをプログラムで設定する

ViewController.SwiftファイルにUITextFieldDelegateを実装します(例:ViewController:UIViewController、UITextFieldDelegate {)クラス。

 lazy var firstNameTF: UITextField = {

    let firstname = UITextField()
    firstname.placeholder = "FirstName"
    firstname.frame = CGRect(x:38, y: 100, width: 244, height: 30)
    firstname.textAlignment = .center
    firstname.borderStyle = UITextBorderStyle.roundedRect
    firstname.keyboardType = UIKeyboardType.default
    firstname.delegate = self
    return firstname
}()

lazy var lastNameTF: UITextField = {

    let lastname = UITextField()
    lastname.placeholder = "LastName"
    lastname.frame = CGRect(x:38, y: 150, width: 244, height: 30)
    lastname.textAlignment = .center
    lastname.borderStyle = UITextBorderStyle.roundedRect
    lastname.keyboardType = UIKeyboardType.default
    lastname.delegate = self
    return lastname
}()

lazy var emailIdTF: UITextField = {

    let emailid = UITextField()
    emailid.placeholder = "EmailId"
    emailid.frame = CGRect(x:38, y: 200, width: 244, height: 30)
    emailid.textAlignment = .center
    emailid.borderStyle = UITextBorderStyle.roundedRect
    emailid.keyboardType = UIKeyboardType.default
    emailid.delegate = self
    return emailid
}()

// Mark:-デリゲートtextFieldを処理します。

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    view.endEditing(true)
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

    if textField == firstNameTF {

        lastNameTF.becomeFirstResponder()
    }

    else if textField == lastNameTF {

        emailIdTF.becomeFirstResponder()
    }
    else {
        view.emailIdTF(true)
    }
    return true
}

0

関数hidekeyboardを作成し、それを.xibファイルのテキストフィールドにリンクして、DidEndOnExitを選択します

-(IBAction)Hidekeyboard    
{    
      textfield_name.resignFirstResponder;    
}  

0

Interface Builderを使用してビューを作成した場合は、以下を使用します。メソッドを作成するだけで、

-(IBAction)dismissKeyboard:(id)sender
{
[sender resignFirstResponder];
}

ビューのテキストフィールドを右クリックして、イベントを終了時に終了として設定し、それをメソッド「dismissKeyboard」にワイヤリングします。

初心者に最適なガイドは、「Head First iPhone and iPad Development、2nd Edition」です。


0

これを試して

- (BOOL) textView: (UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
{
    if ([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }
    return YES;
}

0
//====================================================
//                  textFieldShouldReturn:
//====================================================
-(BOOL) textFieldShouldReturn:(UITextField*) textField { 
    [textField resignFirstResponder];
    if(textField.returnKeyType != UIReturnKeyDone){
        [[textField.superview viewWithTag: self.nextTextField] becomeFirstResponder];
    }
    return YES;
}

0

Swift 3を探している人

1)UITextFieldのデリゲートがストーリーボードのViewControllerに接続されていることを確認します

2)ViewController.SwiftファイルにUITextFieldDelegateを実装します(例:クラスViewController:UIViewController、UITextFieldDelegate {)

3)以下のデリゲートメソッドを使用する

func textFieldShouldReturn(textField: UITextField) -> Bool { 
   textField.resignFirstResponder()  
return false }

0

これは私がSwift 4.2でキーボードを閉じる方法であり、私にとってはうまくいきます:

    override func viewDidLoad() {
    super.viewDidLoad()

    let tap = UITapGestureRecognizer(target: self, action: 
    #selector(dismissKeyboard))

    view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    numberField.resignFirstResponder()
    }

-2

Swift 3、iOS 9以降

@IBAction private func noteFieldDidEndOnExit(_ sender: UITextField) {}

UPD:それでも私には問題なく動作します。この答えに専念した人は、ストーリーボードでこのアクションをUITextFieldにバインドする必要があることを理解していなかったと思います。


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