Estoy agregando esta respuesta para un ejemplo más completo en swift 3. Básicamente, necesitaba una vista de tipo de código PIN donde tengo múltiples campos de texto que permiten un carácter en cada celda.
como este I comenzó mediante la creación de una subclase de UITextField y un protocolo que define un nuevo func.
protocol MYDeleteActionTextFieldDelegate {
func textFieldDidSelectDeleteButton(_ textField: UITextField) -> Void
}
class MYDeleteActionTextField: UITextField {
var deleteDelegate: MYDeleteActionTextFieldDelegate?
override func deleteBackward() {
// Need to call this before super or the textfield edit may already be in place
self.deleteDelegate?.textFieldDidSelectDeleteButton(self)
super.deleteBackward()
}
}
Luego crea los campos de texto con la nueva subclase e implementa el delegado en su controlador de vista. En mi caso, administro los campos de texto en una matriz para facilitar su uso y diseño las celdas con PureLayout. Les tienda como esta
pinFields var = UITextField
Luego, en viewDidLoad()
, agrego todos los campos de pasador en la matriz de esta manera:
for _ in 1...6 {
let field = EDFDeleteActionTextField.init(forAutoLayout:())
field.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
field.delegate = self
field.deleteDelegate = self
field.textAlignment = .center
field.font = UIFont.newBigTitle()
field.textColor = UIColor.edfBlue()
field.backgroundColor = UIColor.edfWhite()
self.pinFields.append(field)
self.pinView.addSubview(field)
}
Ahora sólo tiene que responder a toda la apropiada delegar métodos y el objetivo textFieldDidChange
que se agregó arriba.
// MARK: UITextFieldDelegate
func textFieldDidChange(textField: UITextField) {
// If the user typed one character, move to the next cell.
if (textField.text?.characters.count == 1) {
let index = pinFields.index(of: textField)
textField.resignFirstResponder()
if (pinFields.count > index! + 1) {
pinFields[index! + 1].becomeFirstResponder()
}
} // If they deleted the character move to previous cell
else if (textField.text?.characters.count == 0) {
let index = pinFields.index(of: textField)
if (index! - 1 >= 0) {
pinFields[index! - 1].becomeFirstResponder()
}
}
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if range.location > 0 {
let index = pinFields.index(of: textField)
// If there is already text in the text field and the next cell is empty - move the newly typed character to that cell.
if (pinFields.count > index! + 1) {
let nextField = pinFields[index! + 1]
if (nextField.text?.characters.count == 0) {
textField.resignFirstResponder()
nextField.becomeFirstResponder()
nextField.text = string
}
}
return false
}
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return false
}
// MARK: EDFDeleteActionTextFieldDelegate
func textFieldDidSelectDeleteButton(_ textField: UITextField) {
// If user clicked delete, and there are no characters, move to previous cell if available.
// If there are characters, it is handled in UITextFieldDelegate
if (textField.text?.characters.count == 0) {
let index = pinFields.index(of: textField)
if (index! - 1 >= 0) {
pinFields[index! - 1].becomeFirstResponder()
}
else {
textField.resignFirstResponder()
}
}
}
Voy a dejar fuera las partes aburridas (como trazar los campos de texto, etc), ya que esta funcionalidad general es útil en más casos que este punto de vista de código PIN, pero la implementación de esta clase de niños y protocolo deberá proporcionar toda la funcionalidad que necesitaría para vistas de tipo similar y resolver la pregunta en cuestión (que probablemente necesite algo similar).
Happy coding.
Ver [respuesta de JacobCaraballo] (http://stackoverflow.com/a/15801258/242933) a a [pregunta similar] (http: // stackoverflow.com/questions/1977934/detect-backspace-in-uitextfield). – ma11hew28