NSDecimalNumber notANumber is not true for letter 'E' - ios

Im trying to apply validation on UITextField in such a way that it should not accept anything rather than decimal number.
I used following delegate method of UITextField:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSDecimalNumber *number2 = [NSDecimalNumber decimalNumberWithString:string];
if (!string || [string length] < 1 || [string isEqualToString:#""] )
{
return YES;
}
if (!number2 || [number2 isEqualToNumber:[NSDecimalNumber notANumber]])
{
return NO;
}
return YES;
}
Its working perfect,but it has two issues.
1. when i'm entering value 'E' or 'e' its accepting it.
2.Once it accepted letter 'E' or 'e',Its accepting all other english letters.

This is from the documentation.
Besides digits, numericString can
include an initial “+” or “–”; a single “E” or “e”, to indicate the
exponent of a number in scientific notation; and a single
NSLocaleDecimalSeparator to divide the fractional from the integral
part of the number.
Maybe you can use NSRegularExpression instead

You should use NSNumberFormatter to validate numeric user input.

Related

how to do validation for username in [objective-c]?

my requirement for validation is to validate username which allows to enter small a-z,and 0-9, and only two symbol _ and .(dot)
but symbol do not repeat.
and symbol not allowed at the starting of the name.
can any one help me ?? how to do this validation?
i have tried this code but it works fine but it repeats symbol how can i avoid to repeat?
- (BOOL)validateString:(NSString*)stringToSearch
{
NSString *emailRegex = #"[a-z0-9._]{5,15}";
NSPredicate *regex = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", emailRegex];
return [regex evaluateWithObject:stringToSearch];
}
Use the following regex to check if the characters are correct:
^([a-z0-9]+[._])*[a-z0-9]+$
Debuggex Demo
Additionally and separately check the string length. (or use lookaheads)
Edit: it seems like I misread some of the requirements. The above regex disallows symbol at the end of the name as well. If you want to allow symbols there, change the regex to
^([a-z0-9]+[._]?)*$
If you use predicates you can omit the leading ^ and trailing $.
Pure regex approach, used lookahead for count, might have other simplified solution
"(?=[a-z0-9._]{5,15})([a-z0-9][._]?)+"
EDIT
Regarding the additional question: What to avoid the user enter rejected characters
Technically you can achieve that by implementing the UITextViewDelegate method textView(_:shouldChangeTextInRange:replacementText:). But it might give the user impression that the keyboard is not responding correctly.
So it might be a better user experience that implementing textViewShouldEndEditing(_:) method with some kind of alert showing the alert.
define Validation #"abcdefghijklmnopqrstuvwxyz0123456789_."
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSCharacterSet *unacceptedInput = nil;
unacceptedInput = [[NSCharacterSet characterSetWithCharactersInString:ALPHA] invertedSet];
if ([[string componentsSeparatedByCharactersInSet:unacceptedInput] count] <= 1) {
int newLength = (int)textField.text.length + (int)string.length - (int)range.length;
if (newLength > 50) {
return false;
} else {
return true;
}
} else {
return false;
}
}
here I had to also put validation for text length not exceed 50 characters in my project so you can remove that condition

Limiting user input in a UITextField to a certain range of numbers (not number of characters)

I would like to limit user input in a UITextField to 1-105. I have set the delegate and have successfully limited the actual number of characters via the following code, found elsewhere on Stackoverflow. Is there something that I can add in order to force the user to input any integer between 1 and 105?
#define MAXLENGTH 2
- (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSUInteger oldLength = [_startLevel.text length];
NSUInteger replacementLength = [string length];
NSUInteger rangeLength = range.length;
NSUInteger newLength = oldLength - rangeLength + replacementLength;
BOOL returnKey = [string rangeOfString: #"\n"].location != NSNotFound;
return newLength <= MAXLENGTH || returnKey;
}
I am using the number keypad, so the user is already limited to entering numbers. I just need to find something that will make them input something in the range.
Thanks in advance.
First convert the string to a number. In order of ease of use and lack of control, the ways you do that are -[NSString integerValue]*, NSNumberFormatter, and NSScanner. The formatter will give you an NSNumber from which you can then get the integerValue*; the other two get you primitives directly.
Once you have that, compare the number to the endpoints of your range, creating a boolean. Combine that boolean with the other two -- for length and lack of newline -- you already have, and return the result.
*For floating point, either floatValue or doubleValue.
In didEndEditing, get the text, convert it to an integer, and check the value. If it's out of range, display an error message. You might also reset the text to it's previous value, assuming it starts out in-range.
I've used a regular expression to validate inputs to the right format. I found some documentation on line on RegEx that I was able to use to build my expression. You might create a regular expression that requires the input to be 1, 2, or 3 digits. I'm no expert, but the string #"^[0-9]{1,3}$" should require 1 to 3 digits between 0 and 9 (the 0-9 defines the legal characters, and the {1,3} means that the user can enter 1 through 3 of them. The ^ at the beginning anchors the expression to the beginning of the string, and the "$" at the end anchors the expression to the end of the string.)
You can use the code below
NSString *numberRegex = #"[1-9]||[0-9][1-9]||[0-1]0[0-5]";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", numberRegex];
BOOL b = [emailTest evaluateWithObject:numberField.text];
if (b)
{
//Code when number is in the range 1-105
}
else
{
//Code when number is not in the range 1-105
}
Hope this helps you

format uiTextField for phoneNumber and date

I'm using parse to store my data. I have a bunch of UITextField for user registration inside a view controller.
Now, in my phone text field, how do I format the text field to show the following depending on the total length.
+55 (21) 99999-9999 = 13 numbers
+55 (21) 9999-9999 = 12 numbers
I want to accept both 12 and 13 numbers and show the formatted phone in the textfield.
Now, for saving it to parse, I would like to save the formatted number with characters +, (, ), -.
I would also like to format my date text field to dd/mm/yyyy. Can anyone help me?
Thanks.
UPDATE
Ok, so I did the following:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (_telefoneTextField.text.length == 0)
_telefoneTextField.text = [NSString stringWithFormat:#"(%#",_telefoneTextField.text];
if (_telefoneTextField.text.length == 3)
_telefoneTextField.text = [NSString stringWithFormat:#"%#) ",_telefoneTextField.text];
if (_telefoneTextField.text.length == 9)
_telefoneTextField.text = [NSString stringWithFormat:#"%#-",_telefoneTextField.text];
return YES;
}
and
else if (textField == self.telefoneTextField)
{
if (_telefoneTextField.text.length == 14)
{
NSLog(#"Telefone sem o 9");
[self.nascimentoTextField becomeFirstResponder];
}
if (_telefoneTextField.text.length == 15)
{
NSLog(#"Telefone COM o 9");
NSMutableString *telefone = [[NSMutableString alloc] initWithString:_telefoneTextField.text];
[telefone deleteCharactersInRange:NSMakeRange(9,1)];
[telefone insertString:#"-" atIndex:10];
NSLog(#"%#", telefone);
_telefoneTextField.text = telefone;
[self.nascimentoTextField becomeFirstResponder];
}
else
{
NSLog(#"Telefone NAO esta no formato");
}
}
now, it works like I wanted. It changes the format in real time when the user is typing and when finish editing it checks to see how many chars, in case of 15, it changes the format again.
Now, one thing I couldn't do: How can I delete the phone number using the keyboard, I mean, it does't delete the numbers before the "-"character.
Thanks.
The best way to implement this by using regular expressions. See the following discussion
Regex not working correctly on iOS

rangeOfString and NSNotFound result not what i expected

I'm at bit of a loss here, I'm obviously doing something wrong and haven't grasped the way rangeOfString works.
I have a number of textfields and on certain of them, the phone and fax ones, i want to only permit a small range of values 1234567890+-() to be entered
I'm trying to use textfield: shouldChangeCharactersInRange: replacementString: to not return the characters if they fall outside the specified set of characters.
My method is below and below that is an example of the log .
The code for not returning a ';' works fine, as does the code making sure its only the phone and fax number fields that are being tested.
however what happens is it doesn't matter what character i enter - a '1' or '2' a letter or symbol, i get the same result NSNotFound.
Any idea where i am going wrong ?
Cheers
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if ([string isEqualToString:#";"]) {
return NO;
}
if( ([textField.placeholder isEqualToString:self.locationFieldNames[phoneNumber]]) | ([textField.placeholder isEqualToString:self.locationFieldNames[faxNumber]])){
NSString *includeString = #"1234567890-()+";
if ([string rangeOfString:includeString].location == NSNotFound) {
DLog(#"%# is NSNOTFOUND", string);
return NO;
} else {
DLog(#"%# is !NSNOTFOUND", string);
return YES;
}
}
DLog(#"got here");
return YES;
}
and example from the log
2013-11-12 12:59:19.832 SplashDL[4138:70b] -[DiveFacilityDetailViewController textField:shouldChangeCharactersInRange:replacementString:] 1 is NSNOTFOUND
2013-11-12 12:59:24.556 SplashDL[4138:70b] -[DiveFacilityDetailViewController textField:shouldChangeCharactersInRange:replacementString:] q is NSNOTFOUND
2013-11-12 12:59:26.806 SplashDL[4138:70b] -[DiveFacilityDetailViewController textField:shouldChangeCharactersInRange:replacementString:] ! is NSNOTFOUND
You have made misstake in following line of code:
if ([string rangeOfString:includeString].location == NSNotFound)
Change it to following:
if ([includeString rangeOfString:string].location == NSNotFound)
Also note that user may not only type text but he can also copy/paste it from somewhere. So the length of string may be greater than 1.

How to validate fractional number

I am trying to write a function that returns boolean value if given string is in valid fractional format or not.
e. g. fraction numbers are as follows
2/3,
1 2/3,
6/5,
80/20,
60 1/4,
etc.
-(BOOL)validateFraction:(NSString *)string
{
if(string is valid fraction)
return YES;
else
return NO;
}
You can use regular expressions for that:
-(BOOL)validateFraction:(NSString *)string{
NSString *fractionRegex = #"\\d+(/\\d+)?";
NSPredicate *fractionTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", fractionRegex];
return [fractionTest evaluateWithObject:string];
}
P.S. not also, that that function does not validate against division by zero and does not allow fraction to have sign (+ or -) at front
I found a solution which accepts numbers such as 1/210 2/35 6/8etc.
-(BOOL)validateFraction:(NSString *)string{
NSString *fractionRegex = #"[1-9]?[ ]?[0-9]+/[1-9]+";
NSPredicate *fractionTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", fractionRegex];
return [fractionTest evaluateWithObject:string];
}
You can do something like this:
-(BOOL)validateFraction:(NSString *)string
{
if ([string rangeOfString:#"/"].location == NSNotFound) {
return NO;
}
return YES;
}
This code will only see if the string #"/" appears as substring in the given string.
As you can see, this is a very simple solution, and may work if you know that the strings that you want to test are all numerical valid ones. If you want something more robust, that tests for "invalid" strings, just use regular expressions, like in #Vladimir's answer

Resources