在 Swift 中按回车键时在文本字段之间切换

我正在设计一个 iOS 应用程序,我希望当返回键在我的 iPhone 中按下时,它会指引我到下一个文本字段。

我发现了几个类似的问题,周围都有很好的答案,但是它们恰好都在 Objective-C 中,我正在寻找 Swift 代码,现在这就是我到目前为止得到的:

func textFieldShouldReturn(emaillabel: UITextField) -> Bool{
return true
}

它被放置在连接的文件中,并且控制器与包含文本字段的 UIView 相连,但是我不确定这是否是正确的位置。

好的,我试了一下,得到了这个错误:
//could not find an overload for '!=' that accepts the supplied arguments

func textFieldShouldReturn(textField: UITextField) -> Bool {
let nextTag: NSInteger = textField.tag + 1
// Try to find next responder
let nextResponder: UIResponder = textField.superview!.viewWithTag(nextTag)!
if (nextResponder != nil) {
// could not find an overload for '!=' that accepts the supplied arguments


// Found next responder, so set it.
nextResponder.becomeFirstResponder()
} else {
// Not found, so remove keyboard.
textField.resignFirstResponder()
}
return false // We do not want UITextField to insert line-breaks.
}
85532 次浏览

只需在 textFieldShouldReturn方法中使用 UIResponder 类的 becomeFirstResponder()方法。每个 UIView对象都是 UIResponder的子类。

if self.emaillabel.isEqual(self.anotherTextField)
{
self.anotherTextField.becomeFirstResponder()
}

你可以在 给你的 AppleDoc’s 找到更多关于 becomeFirstResponder()方法的信息。

确保设置了 UITextField委托,并且正确地增加了标记。这也可以通过 Interface Builder 来实现。

这是我找到的一篇 Obj-C 文章的链接: 如何浏览文本字段(下一步/完成按钮)

class ViewController: UIViewController,UITextFieldDelegate {
// Link each UITextField (Not necessary if delegate and tag are set in Interface Builder)
@IBOutlet weak var someTextField: UITextField!


override func viewDidLoad() {
super.viewDidLoad()
// Do the next two lines for each UITextField here or in the Interface Builder
someTextField.delegate = self
someTextField.tag = 0 //Increment accordingly
}


func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Try to find next responder
if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField {
nextField.becomeFirstResponder()
} else {
// Not found, so remove keyboard.
textField.resignFirstResponder()
}
// Do not add a line break
return false
}
}

这种方法需要对表视图和集合视图进行一些更改,但是我想对于简单的表单来说还可以。

将你的 textFields连接到一个 IBOutletCollection,按照它的 y 坐标进行排序,然后在 textFieldShouldReturn(_:)中跳转到下一个文本字段,直到你到达结尾:

@IBOutlet var textFields: [UITextField]!


...


textFields.sortInPlace { $0.frame.origin.y < $1.frame.origin.y }


...


func textFieldShouldReturn(textField: UITextField) -> Bool {
if let currentIndex = textFields.indexOf(textField) where currentIndex < textFields.count-1 {
textFields[currentIndex+1].becomeFirstResponder()
} else {
textField.resignFirstResponder()
}
return true
}

或者看看 样本项目(xcode 7 beta 4)

我已经尝试了很多代码,最后这为我在 Swift 3.0最新版本[2017年3月]工作

“ ViewController”类应该继承“ UITextFieldgenerate”来使代码工作。

class ViewController: UIViewController,UITextFieldDelegate

添加带有恰当标记号的 Text 字段,并使用该标记号将控件根据分配给它的增量标记号带到恰当的文本字段。

override func viewDidLoad() {


userNameTextField.delegate = self


userNameTextField.tag = 0


userNameTextField.returnKeyType = UIReturnKeyType.next


passwordTextField.delegate = self


passwordTextField.tag = 1




passwordTextField.returnKeyType = UIReturnKeyType.go


}

在上面的代码中,“ returKeyType = UIReturnKeyType.Next”将使键盘返回键显示为“ Next”,你还可以根据应用程序更改值,选择“ Join/Go”等。

这个“ textFieldShouldReturn”是一个由 UITextFieldCommittee 控制的方法,这里我们有一个基于 Tag 值增量的下一个字段选择

func textFieldShouldReturn(_ textField: UITextField) -> Bool


{


if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField {


nextField.becomeFirstResponder()


} else {


textField.resignFirstResponder()


return true;


}


return false


}

对于那些不喜欢使用标记的纯粹主义者来说,另一种方法是将 UITextField 委托作为单元格,以保持组件之间的分隔或单向..。

  1. 创建一个新协议来链接 Cell 和 TableViewController。

    protocol CellResponder {
    func setNextResponder(_ fromCell: UITableViewCell)
    }
    
  2. Add the protocol to your cell, where your TextField Delegate is also the cell (I do this in the Storyboard).

    class MyTableViewCell: UITableViewCell, UITextFieldDelegate {
    var responder: CellResponder?
    
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    responder?.setNextResponder(self)
    return true
    }
    }
    
  3. Make your TableViewController conform to the CellResponder protocol (i.e. class MyTableViewController: UITableViewController, CellResponder) and implement the method as you wish. I.e. if you have different cell types then you could do this, likewise you could pass in the IndexPath, use a tag, etc.. Don't forget to set cell.responder = self in cellForRow..

    func setNextResponder(_ fromCell: UITableViewCell) {
    if fromCell is MyTableViewCell, let nextCell = tableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? MySecondTableViewCell {
    
    
    nextCell.aTextField?.becomeFirstResponder()
    
    
    } ....
    }
    

最简单的方法改变到下一个文本字段是这不需要长代码

override func viewDidLoad() {
super.viewDidLoad()


emailTextField.delegate = self
passwordTextField.delegate = self
}




func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == emailTextField {
passwordTextField.becomeFirstResponder()
}else {
passwordTextField.resignFirstResponder()
}
return true
}

Swift 5

在键盘上单击返回键时,可以很容易地切换到另一个 TextField。

  • 首先,视图控制器符合 UITextFieldDelegate并在 ViewController中添加 textFieldShouldReturn(_:)委托方法
  • Interface Builder中从 文本字段拖动到 ViewController。然后选择 delegate选项。 注意: 对所有文本字段执行此操作
  • 为 all < strong > TextFields 创建一个 IBOutlet

    class ViewController: UIViewController, UITextFieldDelegate {
    
    
    @IBOutlet weak var txtFieldName: UITextField!
    @IBOutlet weak var txtFieldEmail: UITextField!
    @IBOutlet weak var txtFieldPassword: UITextField!
    
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if textField == txtFieldName {
    textField.resignFirstResponder()
    txtFieldEmail.becomeFirstResponder()
    } else if textField == txtFieldEmail {
    textField.resignFirstResponder()
    txtFieldPassword.becomeFirstResponder()
    } else if textField == txtFieldPassword {
    textField.resignFirstResponder()
    }
    return true
    }
    }
    

我建议您在 textFieldShouldReturn(_:)中使用 switch 语句。

// MARK: UITextFieldDelegate


func textFieldShouldReturn(_ textField: UITextField) -> Bool {
switch textField {
case nameTextField:
phoneTextField.becomeFirstResponder()
case phoneTextField:
emailTextField.becomeFirstResponder()
case emailTextField:
descriptionTextField.becomeFirstResponder()
default:
textField.resignFirstResponder()
}
return false
}

没有什么特别的,这里是我目前用来改变 textFiled。因此 ViewController 中的代码看起来不错:)。# Swift4

final class SomeTextFiled: UITextField {


public var actionKeyboardReturn: (() -> ())?


override init(frame: CGRect) {
super.init(frame: frame)
super.delegate = self
}


required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("init(coder:) has not been implemented")
}


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


extension SomeTextFiled: UITextFieldDelegate {}




class MyViewController : UIViewController {


var tfName: SomeTextFiled!
var tfEmail: SomeTextFiled!
var tfPassword: SomeTextFiled!


override func viewDidLoad() {
super.viewDidLoad()
tfName = SomeTextFiled(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
tfName.actionKeyboardReturn = { [weak self] in
self?.tfEmail.becomeFirstResponder()
}
tfEmail = SomeTextFiled(frame: CGRect(x: 100, y: 0, width: 100, height: 100))
tfEmail.actionKeyboardReturn = { [weak self] in
self?.tfPassword.becomeFirstResponder()
}
tfPassword = SomeTextFiled(frame: CGRect(x: 200, y: 0, width: 100, height: 100))
tfPassword.actionKeyboardReturn = {
/// Do some further code
}
}
}

Caleb 在 Swift 4.0中的 版本

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let nextField = self.view.viewWithTag(textField.tag + 1) as? UITextField {
nextField.becomeFirstResponder()
} else {
textField.resignFirstResponder()
}
return false
}

附注: textField.superview?对我不起作用

如果你有很多 textfield 组件,那么最好使用一个出口集合,链接 textfields 并从 Interface Builder 设置 Return Key

@IBOutlet var formTextFields: [UITextField]!


override func viewDidLoad() {
for textField in formTextFields {
textField.delegate = self
}
}


extension RegisterViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let componentIndex = formTextFields.firstIndex(of: textField) {
if textField.returnKeyType == .next,
componentIndex < (formTextFields.count - 1) {
formTextFields[componentIndex + 1].becomeFirstResponder()
} else {
textField.resignFirstResponder()
}
}
return true
}
}

我对你的问题有一个很好的解决办法。

步骤:

从故事板设置你的返回键。

enter image description here

2-在你的快速档案。

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField.returnKeyType == .next {
Email.resignFirstResponder()
Password.becomeFirstResponder()
} else if textField.returnKeyType == .go {
Password.resignFirstResponder()
self.Login_Action()
}
return true
}

不要忘记设置 Textfield 的委托。

谢谢

Swift 4.2

这是一个 更通用,更简单解决方案,您可以使用任何数量的文本字段此代码。 只需继承 UITextField 委托并根据顺序更新 文本字段标签并复制此函数即可

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let txtTag:Int = textField.tag


if let textFieldNxt = self.view.viewWithTag(txtTag+1) as? UITextField {
textFieldNxt.becomeFirstResponder()
}else{
textField.resignFirstResponder()
}


return true
}

快速编程

class MyViewController: UIViewController, UITextFieldDelegate {


let textFieldA = UITextField()
let textFieldB = UITextField()
let textFieldC = UITextField()
let textFieldD = UITextField()


var textFields: [UITextField] {
return [textFieldA, textFieldB, textFieldC, textFieldD]
}


override func viewDidLoad() {
// layout textfields somewhere
// then set delegate
textFields.forEach { $0.delegate = self }
}


func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let selectedTextFieldIndex = textFields.firstIndex(of: textField), selectedTextFieldIndex < textFields.count - 1 {
textFields[selectedTextFieldIndex + 1].becomeFirstResponder()
} else {
textField.resignFirstResponder() // last textfield, dismiss keyboard directly
}
return true
}
}

你可以用字段标签,我觉得这样比较容易。

首先你要在这里输入代码给你的字段添加标签。

在我的代码上 usernameField 标签是0,passwordField 标签是1。我检查我的标签。然后执行 process。

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField.tag == 0 {
passwordField.becomeFirstResponder()
} else if textField.tag == 1 {
self.view.endEditing(true)
loginFunc()
} else {
print("Hata var")


}
return false
}

如果点击用户名字段返回,输入密码。 或者,如果单击“何时返回密码字段”,则运行登录函数来登录。

Swift 4 + 这段代码会帮助你。

class YOURClass: UITextFieldDelegate {
override func viewDidLoad() {


//delegate your textfield in here
choosenTextField1.delegate = self
choosenTextField2.delegate = self


}


func textFieldShouldReturn(_ textField: UITextField) -> Bool {
switch textField.tag {
case 1:
choosenTextField1.becomeFirstResponder()
case 2:
choosenTextField2.becomeFirstResponder()
default:
break
}
        

return true
}
}

ViewWithTag 是一个糟糕的解决方案,因为 superview 可能有设置了标签的视图:

public extension Collection where Element: Equatable {
func element(after element: Element) -> Element? {
guard let index = firstIndex(of: element) else { return nil }
let nextIndex = self.index(after: index)
return nextIndex < endIndex ? self[nextIndex] : nil
}
}


class Controller: UIViewController {


@IBOutlet weak var firstNameTextField: UITextField!
@IBOutlet weak var lastNameTextField: UITextField!
@IBOutlet weak var companyTextField: UITextField!


private lazy var primaryTextFields: [UITextField] = {
[firstNameTextField, lastNameTextField, companyTextField]
}()


override func viewDidLoad() {
super.viewDidLoad()
primaryTextFields.forEach { $0.delegate = self }
}
}


extension Controller: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let next = primaryTextFields.element(after: textField) {
next.becomeFirstResponder()
} else if primaryTextFields.contains(textField) {
textField.resignFirstResponder()
}
return true
}
}