编辑UITextField时如何关闭键盘


181

我知道当我要分配键盘时,我需要告诉UITextField退出第一响应者,但是我不确定如何知道用户何时按下了键盘上的“完成”键。我可以留意通知吗?


2
[self.view endEditing:YES]; 接触开始代表是最好的解决方案
Zar E Ahmer 2014年

Answers:


351

我将的代表设置UITextField为我的ViewController班级。

在该类中,我按以下方式实现了此方法:

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

参见上面的示例...将IntefaceBuilder连接到您正在用作控制器的对象上的操作...每当用户关闭文本输入系统(按下完成)时,都会调用此操作...
Jason Coco

2
这两种方法都将起作用-当用户按下Return键(无论如何)时,文本字段发送其操作,并发送其委托-textFieldShouldReturn:。
诺亚·威瑟斯庞

顺便说一句-这也适用于UISearchBar。例如,我的代码中有一个成员IBOutlet searchBarTusb;当单击我的“返回键”(UIReturnKeySearch)时,-(void)searchBarSearchButtonClicked :,我输入了[searchBarTusb resignFirstResponder]语句;还要注意,“返回键”是使用Interface Builder在NIB中设置的。
mobibob 2010年

为什么要返回NO而不是YES
Iulian Onofrei,

@IulianOnofrei返回按钮的默认行为是添加行返回并保持键盘在屏幕上。通过返回,NO您可以避免在文本中添加一行返回。
kubi

47

如果将文本字段的DidEndOnExit事件连接到InterfaceBuilder中的一个动作(IBAction),则当用户关闭键盘(带有返回键)时,它将收到消息,并且发送者将是触发该事件的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将发送“退出时结束结束”事件,因此这是您需要链接到控制器的事件。我认为这种方法比上面概述的方法容易。
kubi

2
您能否编辑此答案,以便提及要关联的WHICH事件?这显然比设置委托更好。
Dan Rosenstark 2010年

1
想要赞成这个答案,但是直到它提到DidEndOnExit事件才可以。如果没有OP,请具有编辑权限的人进行更改?
詹姆斯·哈特

32

您也可以在控制器中创建方法

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

然后在IB的连接检查器中,将事件“退出时结束”连接到该事件。


1
这几乎是不正确的,或者至少没有抓住重点。订阅DidEndOnExit活动,您无需致电resignFirstResponder。您可以通过在上放置符号断点来进行测试[UIResponder resignFirstResponder]。请注意,即使您不调用resignFirstResponder,它仍然会被系统调用。马特· 诺伊伯格
克里斯·

19

kubi,谢谢。您的代码有效。只要是明确的(新手喜欢)你说你要设置UITextFielddelegate等于到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此处设置文本字段。如上所述,您不必以编程方式执行此操作。两种方法都可以正常工作。
罗布

18

这是一个无需任何代码即可自动关闭键盘的行为的技巧。在笔尖中,在身份检查器中编辑“第一响应者”代理对象,添加一个新的“第一响应者”操作;让我们称之为dummy:。现在,将文本字段的“退出时结束结束”事件挂钩到“ dummy:第一响应者”代理对象的操作。而已!由于文本字段的“退出时结束结束”事件现在具有一个“操作目标”对,因此,当用户单击“返回”时,文本字段会自动关闭其键盘。并且由于没有为在响应方链上发送的消息寻找处理程序而没有任何惩罚,因此即使在dummy:任何地方都没有实现,该应用程序也不会崩溃。


@matt我发现,如果我添加了放宽键并连接了didEndOnExit事件,那么按下Return键将触发放宽键。如果没有事件连接,则不会触发segue。很好,但是吗?有什么意见吗?顺便说一句:我有您的Swift(已完成)和iOS10(第6章)书籍。他们极大地帮助了我!
Verticon

@Verticon问题与答案与segue无关,所以我不明白这个问题... :(这纯粹是关于键盘解雇的问题
matt

@matt对不起,伙计。我很支持我,因为1)我在处理如何处理UITextField的return键时遇到了这个线程;2)这是一个与您互动的机会(大本书的感谢)。没有“问题”。我只是对为什么/如何工作的方式缺乏了解。
Verticon

@Verticon我很抱歉无法提供帮助。如果我有用的话,请随时提出一个包含更多信息的新问题(演示项目?),并让我高兴。
马特


11

只需添加

[textField endEditing:YES];

您要在其中禁用键盘并显示选择器视图的位置。


10

在Swift中,您可以在Controller中编写IBAction 并将文本字段的Did End End 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];

  }

如果您有许多Uitextfields最好的:

- (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

2

您会注意到,方法“ textFieldShouldReturn”提供了按DONE键的文本字段对象。如果设置了TAG,则可以打开该文本字段。或者,您可以跟踪对象的指针并将其与创建者存储的某些成员值进行比较。

我的学习方法是这样的:

- (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
您能解释一下..如果我在两种情况下都返回否或是,则发生相同的情况,那么在textFieldShouldReturn委托方法中需要返回“是”的原因
K. Jaiswal 2013年

1

这是一种非常干净的方法,可以使用Return键或在后台触摸来结束版本。

在“界面”构建器中,将您的字段嵌入到UIFormView类的视图中

这堂课是什么:

  • 自动将其自身附加为字段委托(从笔尖唤醒或手动添加)
  • 保留对当前编辑字段的引用
  • 退回时关闭键盘或在后台触摸

这是代码:

接口

#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 frame),自动为下一个字段启动版本,...

我个人将其保留在我的框架中,并且始终将其子类化以添加功能,“按原样”通常很有用。

我希望这会有所帮助。欢呼全部


1
有用的课程。有一点,您不应在自己的类前面加上“ UI”前缀。在Objective-C中,您应该使用自己的前缀(“ TL”?),在Swift中,请勿使用任何前缀。
kubi 2015年

谢谢@kubi。那就对了。在我的框架中是MF,就像MooseFactory一样;)
Moose

1

如果要在UIViewController中进行所有编辑,则可以使用。

[[self view]endEditing:YES];

如果要关闭垂直的UITextField键盘,请使用隐藏。

1.在您的viewcontroller.h中添加委托

<UITextFieldDelegate>
  1. 使代表团无法访问您的文本字段。

    self.yourTextField.delegate =自我;

  2. 将此方法添加到您的viewcontroller中。

    -(BOOL)textFieldShouldEndEditing:(UITextField *)textField {[textField resignFirstResponder]; 返回是;}


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
}()

//标记:-处理委托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和iPad开发,第二版”


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的Delegate连接到情节提要中的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。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.