Swift: input cifrada para detalles de UITextField para la tarjeta

Quiero aceptar Card details as input from user . La condición es que los first 10 character will be hidden donde el user will be allowed to enter next 6 character.

He usado cuatro campos de text para esto (mi suposition). Cualquier otra sugerencia es bienvenida.

P.1. ¿Cómo permitir que el usuario ingrese directamente desde el 11º carácter en el tercer campo de text?

Para el campo Fecha de caducidad, he usado dos campos de text.

Q.2. ¿Cómo hacer que el campo de text solo tenga borde en la parte inferior (sin borde izquierdo, derecho y superior)?

introduzca la descripción de la imagen aquí

P.1. ¿Cómo permitir que el usuario ingrese directamente desde el 11º carácter en el tercer campo de text?

A-1: txt3.becomeFirstResponder()

Q.2. ¿Cómo hacer que el campo de text solo tenga borde en la parte inferior (sin borde izquierdo, derecho y superior)?

A-2: utilice la siguiente línea de código:

  func addbottomBorderWithColor(view : UIView, color: UIColor, width: CGFloat) { let border = CALayer() border.backgroundColor = color.CGColor border.frame = CGRectMake(15.0, view.frame.size.height-width, view.frame.size.width,width ) view.layer.addSublayer(border) } 

Había resuelto este problema usando el siguiente enfoque:

  1. Cuatro campos de text con 1º y 2º uno de solo lectura. En el tercer campo de text he colocado la label con dos valores encriptados (es decir, XX) y el tercer campo de text acepta solo dos dígitos. El cuarto campo de text acepta cuatro dígitos.

    Nota: He utilizado este enfoque de label y campo de text porque tengo un número de tarjeta de crédito / débito (14 dígitos) ya desde DB u otra fuente. Necesito aceptar solo los últimos 6 dígitos del usuario y compararlos con el valor existente.

    Cuando el usuario ingresa dos dígitos en el tercer campo de text, salta automáticamente al cuarto campo de text. A partir de entonces, cuando el usuario ingresa cuatro dígitos en el cuarto campo de text, salta automáticamente al campo de text Caducidad del mes seguido del año Caducidad.

  2. setBorderColor function setBorderColor establece solo el color del borde inferior para el mes de caducidad y el campo de text del año.

  3. He agregado UIToolbar with done button al keyboard numérico (establecido durante el time de layout) para todo el campo de text.

Captura de pantalla

A continuación se muestra el código que he usado:

 @IBOutlet weak var txtCardDetails1: UITextField! @IBOutlet weak var txtCardDetails2: UITextField! @IBOutlet weak var txtCardDetails3: UITextField! @IBOutlet weak var txtCardDetails4: UITextField! @IBOutlet weak var txtExpiryMonth: UITextField! @IBOutlet weak var txtExpiryYear: UITextField! let objBlackColor = UIColor.blackColor() let objGreyColor = UIColor.grayColor() 

override func viewDidLoad () {super.viewDidLoad ()

  //Add done button to numeric pad keyboard let toolbarDone = UIToolbar.init() toolbarDone.sizeToFit() let barBtnDone = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: #selector(VerifyCardViewController.doneButton_Clicked(_:))) toolbarDone.items = [barBtnDone] // You can even add cancel button too txtCardDetails3.inputAccessoryView = toolbarDone txtCardDetails4.inputAccessoryView = toolbarDone txtExpiryMonth.inputAccessoryView = toolbarDone txtExpiryYear.inputAccessoryView = toolbarDone // Set an action on EditingChanged event of textfield txtCardDetails3.addTarget(self, action: #selector(VerifyCardViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingChanged) txtCardDetails4.addTarget(self, action: #selector(VerifyCardViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingChanged) txtExpiryMonth.addTarget(self, action: #selector(VerifyCardViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingChanged) setBorderColor(txtExpiryMonth,setBorderColor: objGreyColor) setBorderColor(txtExpiryYear,setBorderColor: objGreyColor) } //Set bottom border color to textfield func setBorderColor(objTextField : UITextField, setBorderColor objColor:UIColor) { let bottomLine = CALayer() bottomLine.frame = CGRectMake(0.0, objTextField.frame.height - 1, objTextField.frame.width, 1.0) bottomLine.backgroundColor = objColor.CGColor objTextField.borderStyle = UITextBorderStyle.None objTextField.layer.addSublayer(bottomLine) } func doneButton_Clicked(sender: AnyObject) { // Hide keyboard when done button is clicked txtCardDetails3.resignFirstResponder() txtCardDetails4.resignFirstResponder() txtExpiryMonth.resignFirstResponder() txtExpiryYear.resignFirstResponder() } func textFieldDidChange(textField: UITextField){ // Change text focus as per condition let text = textField.text if textField.tag == 101 { // Set tag to textfield (if multiple) during design time if text?.utf16.count==2 { txtCardDetails4.becomeFirstResponder() // Move to next text field } } else if textField.tag == 102 { if text?.utf16.count==4 { txtExpiryMonth.becomeFirstResponder() } } else if textField.tag == 103 { if text?.utf16.count==2 { txtExpiryYear.becomeFirstResponder() } } } func textFieldDidBeginEditing(textField: UITextField) { if textField.tag == 103 { // Set border color based on focus setBorderColor(txtExpiryMonth,setBorderColor: objBlackColor) } else if textField.tag == 104 { setBorderColor(txtExpiryMonth,setBorderColor: objBlackColor) } textField.becomeFirstResponder() } func textFieldShouldReturn(textField: UITextField) -> Bool { textField.resignFirstResponder() return true; } //User can enter two digits in textfield with tag 101, 103, 104 and four digits in textfield with tag 102 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if let text = textField.text { let newStr = (text as NSString) .stringByReplacingCharactersInRange(range, withString: string) if newStr.isEmpty { return true } let intvalue = Int(newStr) if textField.tag == 101 || textField.tag == 103 || textField.tag == 104{ return (intvalue >= 0 && intvalue <= 99) ? true : false } else if textField.tag == 102 { return (intvalue >= 0 && intvalue <= 9999) ? true : false } } return true }