it-swarm.com.de

Umschalten zwischen Textfeldern durch Drücken der Return-Taste in Swift

Ich entwerfe eine iOS-App und möchte, dass die Rücktaste in meinem iPhone gedrückt wird, um zum nächsten Textfeld zu gelangen.

Ich habe ein paar ähnliche Fragen gefunden, mit hervorragenden Antworten, aber sie sind alle zufällig in Objective-C und ich suche nach Swift-Code. Jetzt habe ich das bisher:

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

Es befindet sich in der Datei, die mit dem UIView verbunden ist, der die Textfelder enthält, und der Controller. Ich bin mir jedoch nicht sicher, ob dies der richtige Ort ist.

Ich bin in Swift grundsätzlich neu, also erkläre jeden kleinen Schritt oder ich schaffe es irgendwie, es durcheinander zu bringen. Ich verwende auch die neueste Version von Xcode, wenn das einen Unterschied macht.

okay, ich habe es ausprobiert und diesen Fehler bekommen:
//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.
}

Vielen Dank im Voraus, Freunde!

45
lucas rodriguez

Swift 3.0 (Bearbeitungsverlauf für Vorgängerversionen prüfen):

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

Stellen Sie sicher, dass Ihre UITextField-Delegaten gesetzt sind und die Tags ordnungsgemäß inkrementiert werden. Dies kann auch über den Interface Builder erfolgen.

Hier ist ein Link zu einem Obj-C-Beitrag, den ich gefunden habe: Wie man durch Textfelder navigiert (Next/Done-Buttons)

117
Caleb

Swift 4

Sie können leicht zu einem anderen TextField wechseln. 

  • Fügen Sie UITextFieldDelegate hinzu und fügen Sie die textFieldShouldReturn(_:)-Methode in ViewController hinzu. 
  • Ziehen Sie von TextField nach ViewController in Interface Builder . Wählen Sie dann die delegate-Eigenschaft aus. Hinweis : Dies für alle Textfelder tun
  • Erstellen Sie eine IBOutlet für alle 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
      }
    }
    
13
Vinoth Vino

Ich schlage vor, dass Sie die switch-Anweisung in textFieldShouldReturn(_:) verwenden.

// 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
}
11
kubacizek

Dieser Ansatz erfordert einige Änderungen in den Tabellenansichten und in den Auflistungsansichten, ist aber für einfache Formulare in Ordnung, denke ich.

Verbinden Sie Ihre textFields mit einer IBOutletCollection, sortieren Sie sie nach ihrer y-Koordinate und springen Sie in textFieldShouldReturn(_:) einfach zum nächsten Textfeld, bis Sie das Ende erreichen:

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

Oder schauen Sie sich einfach das Beispielprojekt an (xcode 7 beta 4)

7
libec

Ich habe viele Codes ausprobiert und dies hat schließlich in Swift 3.0 Latest [March 2017] funktioniert

Die "ViewController" -Klasse sollte das "UITextFieldDelegate" erben, damit dieser Code funktioniert.

class ViewController: UIViewController,UITextFieldDelegate  

Fügen Sie das Textfeld mit der richtigen Tag-Nummer hinzu und diese Tag-Nummer wird verwendet, um das Steuerelement auf der Grundlage der ihm zugewiesenen inkrementellen Tag-Nummer in das entsprechende Textfeld zu bringen.

override func viewDidLoad() {

 userNameTextField.delegate = self

        userNameTextField.tag = 0

        userNameTextField.returnKeyType = UIReturnKeyType.next

        passwordTextField.delegate = self

        passwordTextField.tag = 1


        passwordTextField.returnKeyType = UIReturnKeyType.go

}

Im obigen Code, der "returnKeyType = UIReturnKeyType.next", wobei die Rücktaste des Tastenfelds als "Weiter" angezeigt wird, haben Sie auch andere Optionen wie "Join/Go" usw., abhängig von Ihrer Anwendung, die Werte ändert.

Diese "textFieldShouldReturn" ist eine von UITextFieldDelegate gesteuerte Methode. Hier haben wir die nächste Feldauswahl basierend auf der Tag-Wert-Inkrementierung

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

    }

der einfachste Weg, zum nächsten Textfeld zu wechseln, besteht darin, dass kein langer Code erforderlich ist 

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

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? funktioniert nicht für mich

2
coldembrace

Swift 4.2

Dies ist eine allgemeinere und einfachste Lösung. Sie können diesen Code mit einer beliebigen Anzahl von TextFields verwenden. Erben Sie einfach UITextFieldDelegate und aktualisieren Sie das Textfeld-Tag entsprechend der Reihenfolge und kopieren Sie diese Funktion

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
}
2
Lahiru Pinto

Verwenden Sie einfach die becomeFirstResponder()-Methode der UIResponder-Klasse in Ihrer textFieldShouldReturn-Methode. Jedes UIView-Objekt ist eine Unterklasse von UIResponder.

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

Weitere Informationen zur becomeFirstResponder()-Methode finden Sie in hier .

2

Schnell/Programmatisch

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
    }
}
1
T. Wei

Eine alternative Methode für Puristen, die keine Tags verwenden möchten und der UITextField-Delegat die Zelle sein soll, um die Komponenten getrennt oder unidirektional zu halten.

  1. Erstellen Sie ein neues Protokoll, um die Zellen und den TableViewController zu verbinden.

    protocol CellResponder {
      func setNextResponder(_ fromCell: UITableViewCell)
    }
    
  2. Fügen Sie das Protokoll Ihrer Zelle hinzu, wobei Ihr TextField-Delegat auch die Zelle ist (ich mache dies im Storyboard).

    class MyTableViewCell: UITableViewCell, UITextFieldDelegate {
      var responder: CellResponder?
    
      func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        responder?.setNextResponder(self)
        return true
      }
    }
    
  3. Machen Sie Ihren TableViewController mit dem CellResponder-Protokoll (d. H. class MyTableViewController: UITableViewController, CellResponder) konform und implementieren Sie die Methode nach Ihren Wünschen. Das heißt Wenn Sie unterschiedliche Zelltypen haben, können Sie dies tun. Ebenso können Sie den IndexPath übergeben, ein Tag verwenden usw. Vergessen Sie nicht, cell.responder = self in cellForRow zu setzen.

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

Wenn Sie viele Textfeldkomponenten haben, könnte es besser sein, eine Outlet-Sammlung zu verwenden, Textfelder zu verknüpfen und den Return-Schlüssel vom Schnittstellen-Generator festzulegen 

@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
  }
}
0
antonio.reyes

Kein besonderes, hier verwende ich momentan, um das Textfeld zu ändern. Der Code in ViewController sieht also gut aus :). # 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
        }
    }
}
0
Stephen Chen

Ich habe eine gute Lösung für Ihre Frage.

SCHRITT:

1 - Legen Sie die Rückgabetaste im Storyboard fest.

 enter image description here 

2 - In Ihrer Swift-Datei.

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 - Vergessen Sie nicht, den Delegaten des Textfeldes festzulegen.

Vielen Dank :)

0
Parth Patel