I am using UITextField and i want that should take character in the format of xx-xx-xxx only numbers.
any help ?
Try below it will work
Objective-C
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
int groupingSize = 2;
if([string length] == 0) {
groupingSize = 4;
}
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init] ;
NSString *separator = @"-";
[formatter setGroupingSeparator:separator];
[formatter setGroupingSize:groupingSize];
[formatter setUsesGroupingSeparator:YES];
[formatter setSecondaryGroupingSize:2];
if (![string isEqual: @""] && (textField.text != nil && textField.text.length > 0)) {
NSString *num = textField.text;
num = [num stringByReplacingOccurrencesOfString:separator withString:@""];
NSString *str = [formatter stringFromNumber:[NSNumber numberWithDouble:[num doubleValue]]];
textField.text = str;
}
return YES;
}
Swift-3
extension ViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
var groupSize = 2
let separator = "-"
if string.characters.count == 0 {
groupSize = 4
}
let formatter = NumberFormatter()
formatter.groupingSeparator = separator
formatter.groupingSize = groupSize
formatter.usesGroupingSeparator = true
formatter.secondaryGroupingSize = 2
if var number = textField.text, string != "" {
number = number.replacingOccurrences(of: separator, with: "")
if let doubleVal = Double(number) {
let requiredString = formatter.string(from: NSNumber.init(value: doubleVal))
textField.text = requiredString
}
}
return true
}
}
You can call path into this method any pattern you need for your textField:
extension String {
func applyPatternOnNumbers(pattern: String, replacmentCharacter: Character) -> String {
var pureNumber = self.replacingOccurrences( of: "[^0-9]", with: "", options: .regularExpression)
for index in 0 ..< pattern.count {
guard index < pureNumber.count else { return pureNumber }
let stringIndex = String.Index(encodedOffset: index)
let patternCharacter = pattern[stringIndex]
guard patternCharacter != replacmentCharacter else { continue }
pureNumber.insert(patternCharacter, at: stringIndex)
}
return pureNumber
}
}
Example:
guard let text = textField.text else { return }
textField.text = text.applyPatternOnNumbers(pattern: "##-##-###", replacmentCharacter: "#")
Had a need to do this nicely for a phone numbers with a variable format, here's what I wrote. Feel free to reuse - First I've got a method to filter a formatted string, with # being a number, and any other character being some kind of "filler" that should be conveniently inserted after the user gets to the place where it's needed.
NSMutableString *filteredPhoneStringFromStringWithFilter(NSString *string, NSString *filter)
{
NSUInteger onOriginal = 0, onFilter = 0, onOutput = 0;
char outputString[([filter length])];
BOOL done = NO;
while(onFilter < [filter length] && !done)
{
char filterChar = [filter characterAtIndex:onFilter];
char originalChar = onOriginal >= string.length ? '\0' : [string characterAtIndex:onOriginal];
switch (filterChar) {
case '#':
if(originalChar=='\0')
{
// We have no more input numbers for the filter. We're done.
done = YES;
break;
}
if(isdigit(originalChar))
{
outputString[onOutput] = originalChar;
onOriginal++;
onFilter++;
onOutput++;
}
else
{
onOriginal++;
}
break;
default:
// Any other character will automatically be inserted for the user as they type (spaces, - etc..) or deleted as they delete if there are more numbers to come.
outputString[onOutput] = filterChar;
onOutput++;
onFilter++;
if(originalChar == filterChar)
onOriginal++;
break;
}
}
outputString[onOutput] = '\0'; // Cap the output string
return [NSString stringWithUTF8String:outputString];
}
Now so that they can delete through filler, I modified my should change characters in range.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *filter = @"(###) ### - ####";
if(!filter) return YES; // No filter provided, allow anything
NSString *changedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if(range.length == 1 && // Only do for single deletes
string.length < range.length &&
[[textField.text substringWithRange:range] rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"0123456789"]].location == NSNotFound)
{
// Something was deleted. Delete past the previous number
NSInteger location = changedString.length-1;
if(location > 0)
{
for(; location > 0; location--)
{
if(isdigit([changedString characterAtIndex:location]))
{
break;
}
}
changedString = [changedString substringToIndex:location];
}
}
textField.text = filteredPhoneStringFromStringWithFilter(changedString, filter);
return NO;
}
This provides a really clean way to force users to enter numbers in a particular format.
Implement your logic inside textField:shouldChangeCharactersInRange:replacementString:
which is a delegate method.