I have a Verification ViewController
, I get 4 digit verification code by SMS and I need to enter those code to login, I have created the ViewController
Provide the tag to the textfield like 1,2,3,4 and directly use it
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
let next:NSInteger
if string == "" {
next = textField.tag - 1;
}
else{
next = textField.tag + 1;
}
if (textField.text?.characters.count)! >= 1 {
if textField.tag == 4 {
if string == "" {
textField.text = ""
let temptf = self.view.viewWithTag(next) as! UITextField
temptf.becomeFirstResponder()
return false
}
else{
if (textField.text?.characters.count)! > 1 {
let stringg = textField.text!
textField.text = stringg.replacingOccurrences(of: stringg, with: string)
}
return false
}
}
else{
if string == "" {
textField.text = ""
if next != 0 {
let temptf = self.view.viewWithTag(next) as! UITextField
temptf.becomeFirstResponder()
}
return false
}
else{
if (textField.text?.characters.count)! > 1 {
let stringg = textField.text!
textField.text = stringg.replacingOccurrences(of: stringg, with: string)
}
let temptf = self.view.viewWithTag(next) as! UITextField
temptf.becomeFirstResponder()
}
}
}
return true
}
Try this sample tutorial passcode lock
ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController<UITextFieldDelegate>
{
IBOutlet UITextField *txtPassword;
}
@end
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
txtPassword.delegate=self;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 1) ? NO : YES;
}
try this : - For swift 3.0
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// On inputing value to textfield
if ((textField.text?.characters.count)! < 1 && string.characters.count > 0){
let nextTag = textField.tag + 1;
// get next responder
let nextResponder = textField.superview?.viewWithTag(nextTag);
textField.text = string;
if (nextResponder == nil){
textField.resignFirstResponder()
}
nextResponder?.becomeFirstResponder();
return false;
}
else if ((textField.text?.characters.count)! >= 1 && string.characters.count == 0){
// on deleting value from Textfield
let previousTag = textField.tag - 1;
// get next responder
var previousResponder = textField.superview?.viewWithTag(previousTag);
if (previousResponder == nil){
previousResponder = textField.superview?.viewWithTag(1);
}
textField.text = "";
previousResponder?.becomeFirstResponder();
return false;
}
return true;
}
converted Anurag Soni answer in swift 3.0
You just have to implement this method only.
You can change the text field like this by using the delegate function of the text field. Initially, you need to set the delegate and the tag of each text field.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if ((textField.text.length >= 1) && (string.length > 0))
{
NSInteger nextTag = textField.tag + 1;
// Try to find next responder
UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];
if (! nextResponder)
nextResponder = [textField.superview viewWithTag:1];
if (nextResponder)
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
return NO;
}
return YES;
}
Swift 2
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// On inputing value to textfield
if (textField.text?.characters.count < 1 && string.characters.count > 0){
let nextTag = textField.tag + 1;
// get next responder
var nextResponder = textField.superview?.viewWithTag(nextTag);
if (nextResponder == nil){
nextResponder = textField.superview?.viewWithTag(1);
}
textField.text = string;
nextResponder?.becomeFirstResponder();
return false;
}
else if (textField.text?.characters.count >= 1 && string.characters.count == 0){
// on deleting value from Textfield
let previousTag = textField.tag - 1;
// get next responder
var previousResponder = textField.superview?.viewWithTag(previousTag);
if (previousResponder == nil){
previousResponder = textField.superview?.viewWithTag(1);
}
textField.text = "";
previousResponder?.becomeFirstResponder();
return false;
}
return true;
}
Swift 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField.text!.count < 1 && string.count > 0{
let nextTag = textField.tag + 1
// get next responder
var nextResponder = textField.superview?.viewWithTag(nextTag)
if (nextResponder == nil){
nextResponder = textField.superview?.viewWithTag(1)
}
textField.text = string
nextResponder?.becomeFirstResponder()
return false
}
else if textField.text!.count >= 1 && string.count == 0{
// on deleting value from Textfield
let previousTag = textField.tag - 1
// get next responder
var previousResponder = textField.superview?.viewWithTag(previousTag)
if (previousResponder == nil){
previousResponder = textField.superview?.viewWithTag(1)
}
textField.text = ""
previousResponder?.becomeFirstResponder()
return false
}
return true
}
Modified Anurag Soni's answer in Swift 3.
textFields
and the text fields have ordered tags set It prevents from pasting more than one digit
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Restrict to only digits
let aSet = NSCharacterSet(charactersIn:"0123456789").inverted
let compSepByCharInSet = string.components(separatedBy: aSet)
let numberFiltered = compSepByCharInSet.joined(separator: "")
if string != numberFiltered {
return false
}
// Get the unwrapped text
guard let text = textField.text else {
return false
}
if (text.characters.count < 1 && string.characters.count == 1) {
// New value to empty text field
textField.text = string
// Next responder
if let someTextField = (textFields.filter { $0.tag == textField.tag + 1 }).first {
someTextField.becomeFirstResponder()
} else {
view.endEditing(true)
}
return false
} else if (text.characters.count >= 1 && string.characters.count == 0){
// On deleting value from Textfield
textField.text = ""
// Previous responder
if let someTextField = (textFields.filter { $0.tag == textField.tag - 1 }).first {
someTextField.becomeFirstResponder()
} else {
view.endEditing(true)
}
return false
} else if string.characters.count == 1 {
// There's already some digit in text field
// Replace it with new one
textField.text = string
// Next responder
if let someTextField = (textFields.filter { $0.tag == textField.tag + 1 }).first {
someTextField.becomeFirstResponder()
} else {
view.endEditing(true)
}
}
return false
}
I was working on a similar functionality and did it in my way. Solution below. Swift 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
//For clear button pressed
//If the textfield has already text in it
if string.count == 0 {
textField.text = string
return true
}
//For First time entry into the text field
guard let text = textField.text, text.count <= 0 else {
//If user enter second character
return false
}
//For First time entry into the text field
if text.count == 0 {
textField.text = string
textField.resignFirstResponder()
self.nextResponde(tag: textField.tag)
return true
}
return false
}
//To make the next field as responder
func nextResponde(tag: Int) {
switch tag {
case self.PINTextField.tag:
guard let text = self.PINTextField1.text, text.count == 1 else {
self.PINTextField1.becomeFirstResponder()
return
}
case self.PINTextField1.tag:
guard let text = self.PINTextField2.text, text.count == 1 else {
self.PINTextField2.becomeFirstResponder()
return
}
case self.PINTextField2.tag:
guard let text = self.PINTextField3.text, text.count == 1 else {
self.PINTextField3.becomeFirstResponder()
return
}
default:
let _ = tag
}
}