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

时间:2015-08-01 22:39:36

标签: ios iphone swift xcode6

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

我发现了几个类似的问题,并且有很好的答案,但它们恰好都在Objective-C中,我正在寻找Swift代码,现在这就是我现在所拥有的:

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

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

我对swift来说基本上是新手,所以解释每一个小步骤,否则我会以某种方式搞砸它。如果这有任何区别,我也会使用最新版本的Xcode。

好的,所以我试了这个并得到了这个错误:
//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.
}

先谢谢好友!!

16 个答案:

答案 0 :(得分:124)

Swift 3.0 (查看以前版本的修改历史记录):

class ViewController: UIViewController,UITextFieldDelegate 
{
   //Link each UITextField
   @IBOutlet weak var textField: UITextField!

   override func viewDidLoad() 
   {
      super.viewDidLoad()
      // Do this for each UITextField
      textField.delegate = self
      textField.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
   }
}

确保您的UITextField代表已设置且代码正确递增。这也可以通过Interface Builder完成。

这是我发现的Obj-C帖子的链接:How to navigate through textfields (Next / Done Buttons)

答案 1 :(得分:17)

Swift 4

您可以轻松切换到另一个TextField。

  • ViewController
  • 中添加UITextFieldDelegate并添加textFieldShouldReturn(_:)方法
  • 界面生成器中从 TextField 拖动到 ViewController 。然后选择delegate属性。 注意:对所有TextField执行此操作
  • 为所有 TextFields

    创建IBOutlet
    class ViewController: UIViewController, UITextFieldDelegate {
    
      @IBOutlet weak var txtFieldName: UITextField!
      @IBOutlet weak var txtFieldEmail: UITextField!
      @IBOutlet weak var txtFieldPassword: UITextField!
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
      }
    
      //MARK: - Controlling the Keyboard
      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
      }
    }
    

答案 2 :(得分:11)

我建议您在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
}

答案 3 :(得分:8)

这种方法需要对表格视图和集合视图进行一些更改,但我认为它对于简单的表单是可以的。

将您的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
}    

或者只看sample project(xcode 7 beta 4)

答案 4 :(得分:4)

我尝试了很多代码,最后这对我来说非常适合 Swift 3.0最新[2017年3月]

“ViewController”类应继承“UITextFieldDelegate”以使此代码正常工作。

class ViewController: UIViewController,UITextFieldDelegate  

使用正确标记nuber添加文本字段,此标记号用于根据分配给它的增量标记号将控件转移到适当的文本字段。

override func viewDidLoad() {

 userNameTextField.delegate = self

        userNameTextField.tag = 0

        userNameTextField.returnKeyType = UIReturnKeyType.next

        passwordTextField.delegate = self

        passwordTextField.tag = 1


        passwordTextField.returnKeyType = UIReturnKeyType.go

}

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

这个“textFieldShouldReturn”是一个UITextFieldDelegate控制的方法,在这里我们根据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

    }

答案 5 :(得分:3)

更改为下一个文本的最简单方法字段不需要长代码

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
    }

答案 6 :(得分:3)

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
}

P.S。 textField.superview?对我不起作用

答案 7 :(得分:3)

以编程方式快速

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

答案 8 :(得分:2)

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

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

您可以在here的Apple Doc's找到有关becomeFirstResponder()方法的更多信息。

答案 9 :(得分:2)

Swift 4.2

这是一个更通用,最简单的解决方案,您可以将此代码与任意数量的TextField结合使用。 只需继承 UITextFieldDelegate 并根据顺序更新 Textfield标签,然后复制此功能

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
}

答案 10 :(得分:1)

不喜欢使用标签的纯粹主义者的另一种方法,并希望UITextField委托成为保持组件分离或单向的单元格......

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

    protocol CellResponder {
      func setNextResponder(_ fromCell: UITableViewCell)
    }
    
  2. 将协议添加到您的单元格,其中TextField Delegate也是单元格(我在故事板中执行此操作)。

    class MyTableViewCell: UITableViewCell, UITextFieldDelegate {
      var responder: CellResponder?
    
      func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        responder?.setNextResponder(self)
        return true
      }
    }
    
  3. 使您的TableViewController符合CellResponder协议(即class MyTableViewController: UITableViewController, CellResponder)并根据需要实施该方法。即如果你有不同的单元格类型,那么你可以这样做,同样你可以传入IndexPath,使用标签等。不要忘记在cellForRow中设置cell.responder = self ..

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

答案 11 :(得分:1)

没有任何特别之处,这是我目前正在使用的更改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
        }
    }
}

答案 12 :(得分:1)

如果您有很多文本字段组件,那么最好使用插座集合,链接文本字段并从界面构建器设置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
  }
}

答案 13 :(得分:0)

对于您的问题,我有一个很好的解决方案。

步骤:

1-从情节提要中设置返回键。

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
    }

3-不要忘记设置文本字段的委托。

谢谢:)

答案 14 :(得分:0)

您可以使用字段标签。我认为这比其他方法容易。

首先,您要在此处输入代码以为字段添加标签。

在我的代码中,usernameField标签为0,passwordField标签为1。然后检查我的标签。然后进行处理。

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
}

如果单击返回用户名字段,请输入密码。 或者,如果单击“密码返回时”字段,请运行登录功能进行登录。

答案 15 :(得分:0)

斯威夫特 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
  }
}