ios - Cambiar entre campos de texto al presionar la tecla de retorno en Swift
iphone xcode6 (14)
Estoy diseñando una aplicación para iOS y quiero que cuando presione la tecla de retorno en mi iPhone me dirija al siguiente campo de texto siguiente.
He encontrado un par de preguntas similares, con excelentes respuestas, pero todas están en Objective-C y estoy buscando el código Swift, ahora esto es lo que tengo hasta ahora:
func textFieldShouldReturn(emaillabel: UITextField) -> Bool{
return true
}
Se coloca en el archivo que está conectado y el controlador a la UIView que contiene los campos de texto, pero no estoy seguro de si ese es el lugar correcto.
Básicamente soy nuevo en Swift, así que explique cada pequeño paso o me las arreglaré de alguna manera. También estoy usando la última versión de Xcode si eso hace alguna diferencia.
Bien, probé esto y obtuve este error:
//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.
}
Gracias de antemano amigos!
Asegúrese de que sus delegados
UITextField
estén configurados y que las etiquetas se incrementen correctamente.
Esto también se puede hacer a través del Creador de interfaces.
Aquí hay un enlace a una publicación de Obj-C que encontré: Cómo navegar por los campos de texto (botones Siguiente / Listo)
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
}
}
Este enfoque necesita algunos cambios en las vistas de tabla y vistas de colección, pero supongo que está bien para formularios simples.
Conecte sus
textFields
a una
IBOutletCollection
,
IBOutletCollection
por su coordenada y y en
textFieldShouldReturn(_:)
simplemente salte al siguiente campo de texto hasta llegar al final:
// 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
}
O simplemente mira el proyecto de muestra (xcode 7 beta 4)
He probado muchos códigos y finalmente esto funcionó para mí en Swift 3.0 Latest [marzo de 2017]
La clase "ViewController" debería heredar el "UITextFieldDelegate" para que este código funcione.
@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
}
Agregue el campo de texto con el nuber de etiqueta adecuada y este número de etiqueta se usa para llevar el control al campo de texto apropiado según el número de etiqueta incremental asignado a él.
class ViewController: UIViewController,UITextFieldDelegate
En el código anterior, el "returnKeyType = UIReturnKeyType.next", donde hará que la tecla de retorno del teclado numérico se muestre como "Siguiente", también tiene otras opciones como "Unirse / Ir", etc., según su aplicación, cambie los valores.
Este "textFieldShouldReturn" es un método controlado por UITextFieldDelegate y aquí tenemos la siguiente selección de campo basada en el incremento del valor de Tag
override func viewDidLoad() {
userNameTextField.delegate = self
userNameTextField.tag = 0
userNameTextField.returnKeyType = UIReturnKeyType.next
passwordTextField.delegate = self
passwordTextField.tag = 1
passwordTextField.returnKeyType = UIReturnKeyType.go
}
Le sugiero que use la instrucción switch en
textFieldShouldReturn(_:)
.
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var txtFieldName: UITextField!
@IBOutlet weak var txtFieldEmail: UITextField!
@IBOutlet weak var txtFieldPassword: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
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
}
}
No hay ningún especial, aquí está mi uso actual para cambiar el textFiled. Entonces el código en ViewController se ve bien :). # 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
}
}
}
Si tiene muchos componentes de campo de texto, podría ser mejor usar una colección de salida, vincular campos de texto y configurar la clave de retorno desde el generador de interfaces
@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
}
}
Simplemente use el método
becomeFirstResponder()
de la clase UIResponder en su método
textFieldShouldReturn
.
Todos los objetos
UIView
son subclases de
UIResponder
.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let nextField = self.view.viewWithTag(textField.tag + 1) as? UITextField {
nextField.becomeFirstResponder()
} else {
textField.resignFirstResponder()
}
return false
}
Puede encontrar más información sobre el método
becomeFirstResponder()
en Apple Doc''s
here
.
Tengo una buena solución para tu pregunta.
PASO:
1 - Establezca su clave de retorno del guión gráfico.
2 - En tu archivo rápido.
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 - No olvide configurar el delegado del campo de texto.
Gracias :)
Un método alternativo para los puristas que no les gusta usar etiquetas y quieren que el delegado UITextField sea la celda para mantener los componentes separados o unidireccionales ...
-
Cree un nuevo protocolo para vincular Cell''s y TableViewController.
protocol CellResponder { func setNextResponder(_ fromCell: UITableViewCell) }
-
Agregue el protocolo a su celda, donde su Delegado TextField también es la celda (hago esto en el Guión gráfico).
class MyTableViewCell: UITableViewCell, UITextFieldDelegate { var responder: CellResponder? func textFieldShouldReturn(_ textField: UITextField) -> Bool { responder?.setNextResponder(self) return true } }
-
Haga que su TableViewController se ajuste al protocolo CellResponder (es decir,
class MyTableViewController: UITableViewController, CellResponder
) e implemente el método que desee. Es decir, si tiene diferentes tipos de celdas, puede hacer esto, del mismo modo, puede pasar el IndexPath, usar una etiqueta, etc. No olvide establecercell.responder = self
en cellForRow ...func setNextResponder(_ fromCell: UITableViewCell) { if fromCell is MyTableViewCell, let nextCell = tableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? MySecondTableViewCell { nextCell.aTextField?.becomeFirstResponder() } .... }
la forma más fácil de cambiar al siguiente campo de texto es que no es necesario un código largo
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
}
La versión de Caleb en Swift 4.0
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
}
PS
textField.superview?
no funciona para mi
Rápido / Programáticamente
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
}
Swift 4.2
Esta es una solución más genérica y fácil , puede usar este código con cualquier cantidad de TextFields. Simplemente herede UITextFieldDelegate y actualice la etiqueta de campo de texto según el orden y copie esta función
if self.emaillabel.isEqual(self.anotherTextField)
{
self.anotherTextField.becomeFirstResponder()
}
Swift 5
Puede cambiar fácilmente a otro TextField al hacer clic en la tecla de retorno en el teclado.
-
Primero, su controlador de vista se ajusta a
UITextFieldDelegate
y agrega el método delegadotextFieldShouldReturn(_:)
en ViewController -
Arrastre desde
TextField
a
ViewController
en
Interface Builder
.
Luego seleccione la opción
delegate
. Nota : haga esto para todos los TextField -
Crear un
IBOutlet
para todos los TextFieldsfunc textFieldShouldReturn(_ textField: UITextField) -> Bool { let nextTag: NSInteger = textField.tag + 1 // Try to find next responder let nextResponder = 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. }