Je conçois une application iOS et je souhaite que lorsque la touche de retour est enfoncée dans mon iPhone, elle me renvoie au champ de texte suivant.
J'ai trouvé quelques questions similaires, avec d'excellentes réponses, mais elles se trouvent toutes dans Objective-C et je recherche le code Swift. Voici ce que j'ai jusqu'à présent:
func textFieldShouldReturn(emaillabel: UITextField) -> Bool{
return true
}
Il est placé dans le fichier qui est connecté et contrôleur à UIView qui contient les champs de texte, mais je ne suis pas sûr que ce soit le bon endroit.
Je suis fondamentalement nouveau chez Swift, alors expliquez-moi chaque petit pas ou je vais réussir à tout gâcher. J'utilise aussi la dernière version de Xcode si cela fait une différence.
d'accord, j'ai donc essayé et obtenu l'erreur suivante://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.
}
Merci d'avance les copains !!
Swift 3.0 (vérifiez l'historique d'édition pour les versions précédentes):
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
}
}
Assurez-vous que vos délégués UITextField
sont définis et que les balises sont incrémentées correctement. Cela peut également être effectué via Interface Builder.
Voici un lien vers un article d'Obj-C que j'ai trouvé: Comment naviguer dans les champs de texte (boutons Suivant/Terminé)
Swift 4
Vous pouvez facilement passer à un autre TextField.
UITextFieldDelegate
et ajoutez la méthode textFieldShouldReturn(_:)
dans ViewController delegate
. Note : Faites ceci pour tous les TextFieldCréer une IBOutlet
pour tous TextFields
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
}
}
Je suggère que vous devriez utiliser l'instruction switch dans textFieldShouldReturn(_:)
.
// 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
}
Cette approche nécessite quelques modifications dans les vues de table et de collection, mais je suppose qu'elle convient aux formulaires simples.
Connectez votre textFields
à une IBOutletCollection
, triez-la par sa coordonnée y et dans textFieldShouldReturn(_:)
, passez au champ de texte suivant jusqu'à la fin:
@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
}
Ou regardez simplement exemple de projet (xcode 7 beta 4)
J'ai essayé de nombreux codes et cela a finalement fonctionné pour moi dans Swift 3.0 Latest [March 2017]
La classe "ViewController" doit hériter de "UITextFieldDelegate" pour que ce code fonctionne.
class ViewController: UIViewController,UITextFieldDelegate
Ajoutez le champ de texte avec le numéro de balise approprié et ce numéro de balise est utilisé pour amener le contrôle au champ de texte approprié en fonction du numéro de balise incrémentiel qui lui est attribué.
override func viewDidLoad() {
userNameTextField.delegate = self
userNameTextField.tag = 0
userNameTextField.returnKeyType = UIReturnKeyType.next
passwordTextField.delegate = self
passwordTextField.tag = 1
passwordTextField.returnKeyType = UIReturnKeyType.go
}
Dans le code ci-dessus, le code "returnKeyType = UIReturnKeyType.next" où la touche de retour du clavier à afficher en tant que "Suivant" comporte également d'autres options telles que "Rejoindre/Aller", etc., en fonction des modifications apportées par votre application.
Ce "textFieldShouldReturn" est une méthode contrôlée par UITextFieldDelegate et nous avons ici la sélection de champ suivante basée sur l'incrémentation de la valeur de la balise
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
}
le moyen le plus simple de passer au champ de texte suivant est-il inutile d'utiliser un code long
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
}
Caleb's version in 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?
ne fonctionne pas pour moi
Swift 4.2
Ceci est une Plus générique et plus facile Solution, vous pouvez utiliser ce code avec n’importe quelle quantité de TextFields. Il suffit d'hériter UITextFieldDelegate et de mettre à jour la balise Textfield selon l'ordre et de copier cette fonction
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
}
Utilisez simplement la méthode becomeFirstResponder()
de la classe UIResponder dans votre méthode textFieldShouldReturn
. Tous les objets UIView
sont des sous-classes de UIResponder
.
if self.emaillabel.isEqual(self.anotherTextField)
{
self.anotherTextField.becomeFirstResponder()
}
Vous pouvez trouver plus d’informations sur la méthode becomeFirstResponder()
chez Apple Doc dans ici .
Swift/Programmatically
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 {
view.endEditing(true) // last textfield, dismiss keyboard directly
}
return true
}
}
Une méthode alternative pour les puristes qui n'aiment pas utiliser les balises et qui souhaite que le délégué UITextField soit la cellule permettant de garder les composants séparés ou unidirectionnels ...
Créez un nouveau protocole pour lier les cellules et le TableViewController.
protocol CellResponder {
func setNextResponder(_ fromCell: UITableViewCell)
}
Ajoutez le protocole à votre cellule, où votre délégué TextField est également la cellule (je le fais dans le Storyboard).
class MyTableViewCell: UITableViewCell, UITextFieldDelegate {
var responder: CellResponder?
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
responder?.setNextResponder(self)
return true
}
}
Assurez-vous que votre TableViewController est conforme au protocole CellResponder (c'est-à-dire class MyTableViewController: UITableViewController, CellResponder
) et implémentez la méthode à votre guise. C'est à dire. Si vous avez différents types de cellules, vous pouvez le faire, vous pouvez également passer dans IndexPath, utiliser une balise, etc. N'oubliez pas de définir cell.responder = self
dans cellForRow ..
func setNextResponder(_ fromCell: UITableViewCell) {
if fromCell is MyTableViewCell, let nextCell = tableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? MySecondTableViewCell {
nextCell.aTextField?.becomeFirstResponder()
} ....
}
Si vous avez beaucoup de composants de champs de texte, il pourrait être préférable d’utiliser une collection de sorties, de lier des champs de texte et de définir la clé de retour depuis le constructeur d’interface
@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
}
}
Aucune spéciale, voici mon utilisation actuelle pour changer le champ de texte. Donc, le code dans ViewController a l'air 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
}
}
}
J'ai une bonne solution à votre question.
STEP:
1 - Définissez votre clé de retour à partir du storyboard.
2 - Dans votre dossier Swift.
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 - N'oubliez pas de définir le délégué du champ de texte.
Je vous remercie :)