Appending the decimal automatically while typing in the UITextField - ios

I am having a UITextField in which I had limited the number of characters to 4 before decimal and 3 to after decimal. I have done this through
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string{
if (textField == txt_weightKg)
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range
withString:string];
NSString *expression = #"^([0-9]{1,4}+)?(\\.([0-9]{1,3})?)?$";
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:expression
options:NSRegularExpressionCaseInsensitive
error:nil];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString
options:0
range:NSMakeRange(0,
[newString length])];
if (numberOfMatches == 0)
return NO;
}
return YES;
}
This is only for keeping the validation but now I want i actually want is that As soon as I start typing in the UITextfield a decimal is automatically appended with the number. The second condition is that as I reaches the 4 digits the next digit should be after the decimal. For example:-
if I entered 1 it should look like 1. , for 2 digits 11. this has to continue up to 4 digits and then as soon as I eneter the fifth digit it should place that 5th digit after the decimal as 1111.1 which will continue to 3 places after decimal.
If somebody can help me then It will be greatly appreciated! feel free to ask in case of confusion.

I think i achieved what you required by following code:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//create character set containing numbers only
NSCharacterSet * set = [[NSCharacterSet characterSetWithCharactersInString:#"0123456789"] invertedSet];
if (textField.text.length >= 8 && range.length == 0)
{
return NO;
}
else
{
if ([string rangeOfCharacterFromSet:set].location != NSNotFound) {
return NO;
}
else
{
int length = [textField.text length];
//append a decimal after 4 digits
if([textField.text length] ==4 && string.length != 0)
{
textField.text = [NSString stringWithFormat:#"%#.",textField.text];
}
return YES;
}
}
}
Please confirm your response to this.

Related

UITextField accepting only one decimal point with max 3 digits before decimal point & max 2 digits after decimal point

I want to restrict UITextField to accept only one decimal point.
Also maximum 3 digits are allowed before decimal point & maximum 2 digits allowed after decimal point.
Please note that minimum digits can be 1 and decimal cant be entered a first.
How can I achieve it?
You can use below code for the same scenario.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *expression = #"^([0-9]*)(\\.([0-9]+)?)?$";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:nil];
NSUInteger noOfMatches = [regex numberOfMatchesInString:newStr options:0 range:NSMakeRange(0,[newStr length])];
if (noOfMatches==0)
{
return NO;
}
NSUInteger newLength = [textField.text length] + [string length] - range.length;
if(range.length + range.location > textField.text.length)
{
return NO;
}
if ([newStr containsString:#"."])
{
return newLength <= 6;
}
return newLength <= 3;
// return YES;
}
As . is consider as one character. so total would be 6 characters. You can adjust the values in conditions.
This is how you can achieve it using Swift and Regular Expressions:
Set the text field's delegate. This can be done either in code or in IB.
To validate text as it is typed by the user you can add the code to your delegate that is similar to the following:
// Number of digits that are allowed before decimal point
let kMaximumIntegerDigits = 3
// Number of digits that are allowed after decimal point
let kMaximumFractionDigits = 2
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// The replacement string is empty when the user have removed some characters.
if string.isEmpty == true { return true }
// Get the current string the text field holds.
let currentText = textField.text ?? ""
// Check the limits.
if (string.characters.count + currentText.characters.count) > 6 { return false }
// Get the string we are expecting to obtain after the replacement.
var resultingText = currentText
resultingText.insertContentsOf(string.characters, at: currentText.startIndex.advancedBy(range.location))
// Check the final string with the help of the regular expression.
let regex = "^(?:(?:[0-9]{1,\(kMaximumIntegerDigits)}[.][0-9]{0,\(kMaximumFractionDigits)})|(?:[0-9]){1,\(kMaximumIntegerDigits)})$"
let regexRange = resultingText.rangeOfString(regex, options: .RegularExpressionSearch)
if regexRange == nil { return false }
return true
}
Finally, you should verify the resulting text when the user is trying to end an editing session. You can do it like this:
func textFieldShouldEndEditing(textField: UITextField) -> Bool {
// Get the current input string.
guard let currentText = textField.text else { return false }
// Create the regular expression for the final check.
let regex = "^(?:(?:[0-9]{1,\(kMaximumIntegerDigits)}[.][0-9]{1,\(kMaximumFractionDigits)})|(?:[0-9]){1,\(kMaximumIntegerDigits)})$"
let regexRange = currentText.rangeOfString(regex, options: .RegularExpressionSearch)
if regexRange == nil {
// Show an alert to the user with the message that explains what the input is expected...
return false
}
// Make additional clean-up and finalize the editing session.
return true
}
Thank you so much all folks for helping. By referring those answers I framed below answer.
EDIT
While textfields having e.g. 462. & user touches backspace results to 462 which ideally should result to 46
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *strTextField = [textField.text stringByReplacingCharactersInRange:range withString:string];
// restrict textfield from entering ./0 at first place
if (strTextField.length > 0) {
NSString *theCharacterAtIndex0 = [NSString stringWithFormat:#"%c", [strTextField characterAtIndex:0]];
if ([theCharacterAtIndex0 isEqualToString:#"."] || [theCharacterAtIndex0 isEqualToString:#"0"]) {
return NO;
}
}
// NSLog(#"%# , %#", textField.text, strTextField);
// automatically add decimal point after 3 digits entered
if (![textField.text containsString:#"."]) {
if (strTextField.length == MAX_LENGTH_BeforeDecimal && ![strTextField containsString:#"."]) {
strTextField = [strTextField stringByAppendingString:#"."];
textField.text = strTextField;
return NO;
}
}
// when decimal is deleted
if ([textField.text containsString:#"."]) {
if (![strTextField containsString:#"."]) {
int indeOfdecimal = (int)[textField.text rangeOfString:#"."].location;
NSString *strBeforeDecimal = [textField.text substringToIndex:indeOfdecimal];
textField.text = strBeforeDecimal;
}
}
NSArray *separator = [strTextField componentsSeparatedByString:#"."];
// to restrict textfield to single decimal
if([separator count] > 2 ) {
return NO;
}
if([separator count] >= 2) {
// restrict the max digits before & after decimal points
NSString *sepStr0 = [NSString stringWithFormat:#"%#",[separator objectAtIndex:0]];
NSString *sepStr1 = [NSString stringWithFormat:#"%#",[separator objectAtIndex:1]];
if ([sepStr0 length] > 3) {
return NO;
}
if ([sepStr1 length] > 2) {
return NO;
}
}
return YES;
}
Use this regex code:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// Only allow one decimal point and 2 digits after it
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSString *expression = #"^[0-9]{0,3}$*((\\.|,)[0-9]{0,2})?$";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString options:0 range:NSMakeRange(0, [newString length])];
return numberOfMatches != 0;
return YES;
}
The regex used here is "^[0-9]{0,3}$*((\.|,)[0-9]{0,2})?$".
Here number 3 (first bold) denotes the characters before the decimal point and number 2(second bold) denotes the characters after the decimal point.
You can play with this regex and create rule based on your requirement.

How to restrict UITextField to a defined set of characters and limit the length?

I am working on a login and resister view controller. I am limiting usernames to 12 characters and passwords to 16 using :
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(textField==self.userField){
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
return !([newString length] > 12);
}
else if(textField==self.passwordField){
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
return !([newString length] > 16);
}
return YES;
}
this works well but I also want to limit it to a set of characters to stop unwanted symbols and also Chinese characters. I want to define this set:
#define ACCEPTABLE_CHARACTERS #"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
Not sure how to add it to the method above though and get both working. If I was to check for the character set only and not length the code would be:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ACCEPTABLE_CHARACTERS] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
return [string isEqualToString:filtered];
}
Not sure how to combine them though. Can someone help me please? Thanks!
You can do it like (I divided it to function for more readability and easy to scale the conditions)
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
return ([self checkLengthOfString:newString inField:textField] && [self checkCharacter:newString]);
}
// Check Length
- (BOOL)checkLengthOfString:(NSString *)text inField:(UITextField *)textField
{
if(textField == self.userField)
{
return !([text length] > 12);
}
else if(textField == self.passwordField)
{
return !([text length] > 16);
}
}
// Check character
- (BOOL)checkCharacter:(NSString *)text
{
BOOL status = YES;
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ACCEPTABLE_CHARACTERS] invertedSet];
NSRange r = [text rangeOfCharacterFromSet:s];
if (r.location != NSNotFound)
{
status = NO;
}
return status;
}
Why don't you just use a regEx to match that chars?
I know this has already been answered, but I had a similar scenario and I found none of the answers on StackOverflow handled the Backspace character.
I needed to limit input into a UITextField to a specific number of AlphaNumeric characters, but be able to enter spaces.
Also, using [textField length] > kMAXNUMCHARS caused a problem: you couldn't backspace once you hit the max number of chars.
So here's my complete solution. It also disallows leading spaces. Trailing spaces are trimmed elsewhere when the value is saved (in my case to a PLIST file)
In my Constants.h file I defined:
#define ALLOWED_CHARECTERS #" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
extern const int kMAXUSERNAMELENGTH;
then in Constants.m:
const int kMAXUSERNAMELENGTH = 9;
I define my class as UITextFieldDelegate with the line
[self._txtUsername.textField setDelegate:self];
Don't forget to declare the UITextFieldDelegate protocol in your class definiion
#interface MyClass : CCNode <UITextFieldDelegate>
And finally,
//UITextFiledDelegate Protocol method
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
//disallow leading spaces. must allow trailing spaces- never know if we'll add another char
//we trim trailing spaces when we save the TextField value, in our case to Plist file
if (range.location == 0 && [string isEqualToString:#" "])
return NO;
//we use defined ALLOWED_CHARECTERS so we can add chars later, easily.
//we could use [NSCharacterSet alphanumericCharacterSet] if we don't need to allow spaces
NSCharacterSet *allowedInput = [NSCharacterSet characterSetWithCharactersInString:ALLOWED_CHARECTERS];
NSArray* arChar = [string componentsSeparatedByCharactersInSet:allowedInput]; //arChar.count = 1 if 'allowedInput' not in 'string'
//disallow input if its not a backspace (replacementString paramater string equal #"" if a backspace) AND
//(disallow input >= kMAXUSERNAMELENGTH chars, OR disallow if not in allowed allowedChar set
if ( ![string isEqual:#""] && ( [textField.text length] >= kMAXUSERNAMELENGTH || !([arChar count] > 1)) )
return NO;
return YES;
}
I hope this helps someone.

How to insert a string automatically while user editing UITEXTFIELD

I want to my uitextfield be like XXX.XXX.XXX/XX at the end of typing.
To limit the lenght I use this:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField == _cpfField) {
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS_ONLY] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
return (([string isEqualToString:filtered])&&(newLength <= CHARACTER_LIMIT));
} else{
return YES;
}
}
The problem is how to insert the "." and "/" while user still editing it.
The following code should do the following:
Limit the number of characters that can be typed/pasted into the text field
Automatically add periods and slashes at the appropriate locations
Prevent issues from the user copy/pasting a string that already has the necessary periods/slashes
That said, there is almost certainly more efficient ways to do this; but if you're not concerned about code length it'll do the trick just fine.
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *text = textField.text;
// If we're trying to add more than the max amount of characters, don't allow it
if ([text length] == 14 && range.location > 13) {
return NO;
}
// First lets add the whole string we're going for
text = [text stringByReplacingCharactersInRange:range withString:string];
// Now remove spaces, periods, and slashes (since we'll add these automatically in a minute)
text = [text stringByReplacingOccurrencesOfString:#" " withString:#""];
text = [text stringByReplacingOccurrencesOfString:#"." withString:#""];
text = [text stringByReplacingOccurrencesOfString:#"/" withString:#""];
// We need to use an NSMutableString to do insertString calls in a moment
NSMutableString *mutableText = [text mutableCopy];
// Every 4th char will be a '.', but we don't want to check more than the first 8 characters
for (NSUInteger i = 3; i < mutableText.length && i < 8; i += 4) {
[mutableText insertString:#"." atIndex:i];
}
// If the text is more than 11 characters, we also want to insert a '/' at the 11th character index
if (mutableText.length > 11) {
[mutableText insertString:#"/" atIndex:11];
}
// lets set text to our new string
text = mutableText;
// Now, lets check if we need to cut off extra characters (like if the person pasted a too-long string)
if (text.length > 14) {
text = [text stringByReplacingCharactersInRange:NSMakeRange(14, mutableText.length-14) withString:#""];
}
// Finally, set the textfield to our newly modified string!
textField.text = text;
return NO;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *text = textField.text;
text = [text stringByReplacingCharactersInRange:range withString:string];
text = [text stringByReplacingOccurrencesOfString:#"." withString:#""];
// Do your length checking here
NSMutableString *mutableText = [text mutableCopy];
// Every 4th char will be a .
for (NSUInteger i = 3; i < mutableText.length; i += 4) {
[mutableText insertString:#"." atIndex:i];
}
textField.text = mutableText;
return NO;
}
UK National Insurance Number Text Field
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == _txtNationalInsuranceNumber) {
NSString *text = textField.text;
// If we're trying to add more than the max amount of characters, don't allow it
if ([text length] == 13 && range.location > 12) {
return NO;
}
// First lets add the whole string we're going for
text = [text stringByReplacingCharactersInRange:range withString:string];
// Now remove spaces, periods, and slashes (since we'll add these automatically in a minute)
text = [text stringByReplacingOccurrencesOfString:#" " withString:#""];
// We need to use an NSMutableString to do insertString calls in a moment
NSMutableString *mutableText = [text mutableCopy];
// Every 4th char will be a '.', but we don't want to check more than the first 8 characters
for (NSUInteger i = 2; i < mutableText.length && i < 10; i += 3) {
[mutableText insertString:#" " atIndex:i];
}
// If the text is more than 11 characters, we also want to insert a '/' at the 11th character index
if (mutableText.length > 11) {
[mutableText insertString:#" " atIndex:11];
}
// lets set text to our new string
text = mutableText;
// Now, lets check if we need to cut off extra characters (like if the person pasted a too-long string)
if (text.length > 14) {
text = [text stringByReplacingCharactersInRange:NSMakeRange(14, mutableText.length-14) withString:#""];
}
// Finally, set the textfield to our newly modified string!
textField.text = text;
return NO;
}
else
{
return YES;
}
}

Restricting the number of characters entered in UiTextfield by user

I am trying to restrict the number of characters entered in UITextfied,I want the user to enter the numbers in range 40.[0 to 9] to 250.[0 to 9] and the user can only one digit after the decimal point and also he cant enter multiple decimal points. I hope I have made my point clear, so far I have tried some code which is below
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSCharacterSet *nonNumberSet = [[NSCharacterSet characterSetWithCharactersInString:#"0123456789."] invertedSet];
// allow backspace
if (range.length > 0 && [string length] == 0) {
return YES;
}
// do not allow . at the beggining
if (range.location == 0 && [string isEqualToString:#"."]) {
return NO;
}
// set the text field value manually
NSString *newValue = [[textField text] stringByReplacingCharactersInRange:range withString:string];
newValue = [[newValue componentsSeparatedByCharactersInSet:nonNumberSet] componentsJoinedByString:#""];
textField.text = newValue;
// return NO because we're manually setting the value
return NO;
}
So friends please help me further.
Regards
Ranjit

How to validate length and restrict textfield to Numeric, alphanumeric, and alpha characters only in iOS

I want to validate length and restrict Numeric, alphanumeric, and alpha characters only in iOS, can anyone help me out to achieve this.
You can form regular expression strings and use it. Please find a sample a code below for allowing only alphabets and space.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *stringPlace = #"[a-z A-Z]*";
NSPredicate *testPlace = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", stringPlace];
BOOL matches = [testPlace evaluateWithObject:string];
// if it does not match the regular expression and more than 5 characters
if (!matches && string.length > 5)
{
return NO;
}
return YES;
}
Found best Way to tackle this thing. Works like a champ :)
inside .m file
//#define CHARACTERS #" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
//#define CHARACTERS_NUMBERS [CHARACTERS stringByAppendingString:#"1234567890"]
///// Inside shouldChangeCharactersInRange
///////////>>>>>>>>>>>>>>>>>>
if(textField== txtFldAlpha)
{
//Alpha only
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSCharacterSet *unacceptedInput =
[[NSCharacterSet characterSetWithCharactersInString:CHARACTERS] invertedSet];
// Create array of strings from incoming string using the unacceptable
// characters as the trigger of where to split the string.
// If array has more than one entry, there was at least one unacceptable character
if ([[string componentsSeparatedByCharactersInSet:unacceptedInput] count] > 1)
return NO;
else
return YES&&(newLength < 26);
return YES;
}
///////////<<<<<<<<<<<<<<<<<<
///////////>>>>>>>>>>>>>>>>>>
if(textField==txtFldNumeric)
{
//Num only
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSCharacterSet *nonNumberSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([[string componentsSeparatedByCharactersInSet:nonNumberSet] count] > 1)
return NO;
else
return YES&&(newLength < 6);
return YES;
}
///////////<<<<<<<<<<<<<<<<<<
///////////>>>>>>>>>>>>>>>>>>
if(textField==txtFieldNumAlphaSpecial)
{
//Num,Alpha,Special field
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 50) ? NO : YES;
}
///////////<<<<<<<<<<<<<<<<<<

Resources