I want to implement some validation in my project, validation is that: Don't allow number 0-9 and A-Z in UITextField, only allow GUJARATI letter in UITextField. I have tried some validation but It was not working. I need some help from anyone.
I have tried this below code:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
//limit the size :
if([self checkValidation:textField] == true)
{
return NO;
}
return YES;
}
- (BOOL)checkValidation:(UITextField *)textField
{
NSString *rejex = [NSString stringWithFormat:#"%#",#"[A-Za-z0-9]"];
NSPredicate *gujTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", rejex];
//if rejex fullfil than it will return true else false.
return [gujTest evaluateWithObject:textField.text];
}
TIA
In your checkValidation function, you are taking textField as an argument and extracting its text property - but you call it in shouldChangeCharactersInRange, and by that point the text property still holds the old value of text, before the update (it gets updated after you return true from this function). Do instead
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
//limit the size :
if([self checkValidation:string] == true)
{
return NO;
}
return YES;
}
- (BOOL)checkValidation:(NSString *)string
{
let stringWithGujaratiCharacters = "અ" // string with all Gujarati letters
let characterSet = CharacterSet(charactersIn: stringWithGujaratiCharacters).inverted // character set containing every character besides Gujarati letters
return string.rangeOfCharacter(from: characterSet) != nil // returns true if string contains characters other than Gujarati letters
}
If you just don't want to allow latin alphanumeric characters, change your characterSet
let characterSet = CharacterSet.alphanumerics
Change textfield to string on below code. it will work.
if([self checkValidation:string] == true)
and
- (BOOL)checkValidation:(NSString *)textField
{
NSString *rejex = [NSString stringWithFormat:#"%#",#"[A-Za-z0-9]"];
NSPredicate *gujTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", rejex];
//if rejex fullfil than it will return true else false.
return [gujTest evaluateWithObject:textField];
}
For this problem it would be better to use a CharacterSet detection. Regular expression don't work very well with unicode. Also, it is better to check for characters your want to allow than the other way around:
let text = textField.text ?? ""
// https://unicode.org/charts/PDF/U0A80.pdf 0x0A80 ... 0x0AFF
let gurajatiCharacterSet = CharacterSet(charactersIn: Unicode.Scalar(0x0A80 as Int)! ... Unicode.Scalar(0x0AFF as Int)!)
return text.rangeOfCharacter(from: gurajatiCharacterSet.inverted) == nil
Objective-C:
NSUInteger minValue = 0x0A80;
NSUInteger maxValue = 0x0AFF;
NSCharacterSet *gurajatiCharacterSet = [NSCharacterSet characterSetWithRange:NSMakeRange(minValue, maxValue - minValue + 1)];
return [textField.text rangeOfCharacterFromSet:[gurajatiCharacterSet invertedSet]].location == NSNotFound;
For this problem you can use NSCharacterSet.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:#"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"];
for (int i = 0; i < [string length]; i++)
{
unichar c = [string characterAtIndex:i];
if (![myCharSet characterIsMember:c])
{
return NO;
}
}
return YES;
}
Related
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.
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.
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;
}
}
I would like to prevent the user from not entering any data as well as entering only spaces. So basically there must at least be one character without a space. Then I would also like to remove any spaces at the beginning of the word so the first letter is a character that is not a space.
edit
the user must enter something and if the user enters a few spaces before it then I want to trim those spaces. I also want to prevent the user from just entering spaces.
Example
if the user enter's a name and surname like " James Dean" I would like to take the first space away but not the second space between James and Dean.
Set your UIViewController to be your destination UITextField's delegate and implement this method:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// verify the text field you wanna validate
if (textField == _nameTextField) {
// do not allow the first character to be space | do not allow more than one space
if ([string isEqualToString:#" "]) {
if (!textField.text.length)
return NO;
if ([[textField.text stringByReplacingCharactersInRange:range withString:string] rangeOfString:#" "].length)
return NO;
}
// allow backspace
if ([textField.text stringByReplacingCharactersInRange:range withString:string].length < textField.text.length) {
return YES;
}
// in case you need to limit the max number of characters
if ([textField.text stringByReplacingCharactersInRange:range withString:string].length > 30) {
return NO;
}
// limit the input to only the stuff in this character set, so no emoji or cirylic or any other insane characters
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:#"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 "];
if ([string rangeOfCharacterFromSet:set].location == NSNotFound) {
return NO;
}
}
return YES;
}
try like this may be it helps to you,here is my code
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string{
if([text.text length]==0){
if([string isEqualToString:#" "]){
return NO;
}
}
return YES;
}
By placing this code user won't enter space as a first letter but it accepts the space in the middle of the string.
I'll give you a hint for the first part.
NSString *tempname1 = [self.textField.text stringByReplacingOccurrencesOfString:#" " withString:#""];
BOOL thereAreJustSpaces = [tempname1 isEqualToString:#""];
-(void)removeSpacesFromTextFields:(id) sender {
NSString *trim = [self.FNTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if ([trim length] == 0) {
self.FNTextField.text = #"";
}
}
Try this, If you want to prevent space in your text field.
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(checkSpace:) name:UITextFieldTextDidChangeNotification object:textfield];
}
-(void)checkSpace:(NSNotification *)notification
{
str = [textfield.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] ;
textfield.text=str;
}
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