How to put comma and decimals in my UITextField dynamically? - objective-c

I want to add a ',' in '11000' like this '11,000' and decimal ('.') in 465 like 4.65.
I wrote this for Comma :
- (BOOL) textField: (UITextField *)textField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)string {
NSString *unformattedValue;
NSNumberFormatter *formatter;
NSNumber *amount;
switch ([textField tag]) {
case 102:
unformattedValue = [textField.text stringByReplacingOccurrencesOfString:#"," withString:#""];
unformattedValue = [unformattedValue stringByReplacingOccurrencesOfString:#"." withString:#""];
formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setGroupingSeparator:#","];
[formatter setDecimalSeparator:#"."];
amount = [NSNumber numberWithInteger:[unformattedValue intValue]];
textField.text = [formatter stringFromNumber:amount];
break;
default:
break;
}
return YES;
}
And what this doing is it actually putting the comma like this 1,1000 for 11000. And i am not able to do anything close for decimal.
Please help!!

NSNumberFormatter can handle this conversion from string to number and back for you. No need to strip characters yourself with stringByReplacingOccurrencesOfString or use less lenient string to numeric conversion methods like intValue (and at the very least don't use intValue if you want to be able to get a decimal).
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *amount = [formatter numberFromString:textField.text];
textField.text = [formatter stringFromNumber:amount];
Depending on the input you need to tolerate you might still want to do some other cleanup of the input string if NSNumberFormatter's lenient setting is not enough. You could also use multiple number formatters if you wanted to parse an input string in one format and then output it in another.

Use the following code to manually add commas at the right locations. You can get the logic from this code and tweak it to suit your requirement.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSLog(#"Text:%#textField length:%dRange.length:%lu , Range.location:%lu :: replacementString:%#",textField.text,textField.text.length,(unsigned long)range.length,(unsigned long)range.location,string);
NSMutableString *tempString=textField.text.mutableCopy;
int digitsCount;
if ([string isEqualToString:#""]) //digit removed
{
NSLog(#"digit removed, string length after trimming:%d",[tempString stringByReplacingOccurrencesOfString:#"," withString:#""].length);
digitsCount=[tempString stringByReplacingOccurrencesOfString:#"," withString:#""].length-1; //digit removed
}else ///digit added
{
digitsCount=[tempString stringByReplacingOccurrencesOfString:#"," withString:#""].length+1 ;
}
NSLog(#"Number of digits:%d",digitsCount);
switch (digitsCount)
{
//case 1:textField.text=[tempString stringByReplacingOccurrencesOfString:#"," withString:#""];
//break;
case 3:textField.text=[tempString stringByReplacingOccurrencesOfString:#"," withString:#""];
break;
case 4:
//remove previous comma...
tempString=[tempString stringByReplacingOccurrencesOfString:#"," withString:#""].mutableCopy;
[tempString insertString:#"," atIndex:1];
textField.text=tempString;
break;
case 5:
//remove previous comma...
tempString=[tempString stringByReplacingOccurrencesOfString:#"," withString:#""].mutableCopy;
[tempString insertString:#"," atIndex:2];
textField.text=tempString;
break;
case 6:
//remove previous comma...
tempString=[tempString stringByReplacingOccurrencesOfString:#"," withString:#""].mutableCopy;
[tempString insertString:#"," atIndex:1];
[tempString insertString:#"," atIndex:4];
textField.text=tempString;
break;
default:
break;
}
return YES;
}

Related

Formating decimal on fly on a TextField iOS7 Xcode5

I need to achieve this:
When user types (on a textField): 123456
the field will show 123,456
I have the code below, but, for some reason I can figure it out when I type "5" the whole field is reseted to 1.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSString *textt = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSString *formattedString = [formatter stringFromNumber:[NSNumber numberWithFloat:[textt floatValue]]];
textField.text = formattedString;
return NO;
}
it does the job for you, shame on me I could have done it better, but I hope someone can give you a more elegant solution for this issue. (e.g. using regexp or something)
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSNumberFormatter *_formatter = [[NSNumberFormatter alloc] init];
[_formatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSMutableString *_pureNumber = [NSMutableString stringWithString:[textField.text stringByReplacingCharactersInRange:range withString:string]];
[_pureNumber replaceOccurrencesOfString:_formatter.groupingSeparator withString:#"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, _pureNumber.length)];
[textField setText:[_formatter stringFromNumber:#([_pureNumber doubleValue])]];
return NO;
}
so, the general idea is you need to convert back your textt to a number.
the auto-parser cannot do it for you, becasue the after 1,234 the 1,2345 is not a valid number in this formatter, that is why you have got the very first number only, simply the parser chucks everything after the comma , away. (that is a groupingSeparator in this formatter).

NSNumberFormatter unable to allow numbers to start with a 0

So I'm attempting to automatically add slashes between 2 digits when a user enters in their birthday, but for some reason when the birthday starts with a 0, the number formatter erases it and messes up the birthday. I've got my code below, could someone help me figure out how to do this? Thanks in advance!
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init] ;
[formatter setGroupingSeparator:#"/"];
[formatter setGroupingSize:2];
[formatter setUsesGroupingSeparator:YES];
[formatter setSecondaryGroupingSize:2];
NSString *num = textField.text ;
if(![num isEqualToString:#""])
{
num= [num stringByReplacingOccurrencesOfString:#"/" withString:#""];
NSString *str = [formatter stringFromNumber:[NSNumber numberWithDouble:[num doubleValue]]];
textField.text=str;
}
What you could do is the following:
Check the length of the string
If length mod 2 == 0 then add "/"
Log your string
I'm not saying this is recommended but it might help you a bit!
- (void)controlTextDidChange:(NSNotification *)obj{
NSString *num = [textField stringValue] ;
if (num.length%2==0)
{
NSString *someText = [NSString stringWithFormat: #"%#/ ", num];
num = someText;
}
textField.stringValue = num;
}
Something like this may help:
NSMutableString *string = #"YOUR TEXTFIELD TEXT";
NSString *lastString = [string substringWithRange:NSMakeRange(string.length-2, 1)];
if ([lastString isEqualToString:#"/"]) {
return;
}
if (string.length == 2 || string.length == 5) {
[string appendString:#"/"];
}

Customizing UITextField for Currency format works well with iOS 4.x but in iOS 5 gives null

I am customizing UItextField for local currency symbol and comma, using following link :
http://www.thepensiveprogrammer.com/2010/03/customizing-uitextfield-formatting-for.html
NSNumber *actualNumber = [currencyFormatter numberFromString:[mstring
stringByReplacingOccurrencesOfString:localeSeparator withString:#""]];
In iOS 5 this actual number is always null and in iOS 4.x it is working fine
My code's main method for this purpose is :
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField.tag == 1)
{
if(true)
{
NSMutableString* mstring = [[textField text] mutableCopy];
if([mstring length] == 0)
{
//special case...nothing in the field yet, so set a currency symbol first
[mstring appendString:[[NSLocale currentLocale] objectForKey:NSLocaleCurrencySymbol]];
//now append the replacement string
[mstring appendString:string];
}
else
{
//adding a char or deleting?
if([string length] > 0)
{
[mstring insertString:string atIndex:range.location];
}
else
{
//delete case - the length of replacement string is zero for a delete
[mstring deleteCharactersInRange:range];
}
}
NSString* localeSeparator = [[NSLocale currentLocale]
objectForKey:NSLocaleGroupingSeparator];
NSNumber *actualNumber = [currencyFormatter numberFromString:[mstring
stringByReplacingOccurrencesOfString:localeSeparator
withString:#""]];
NSLog(#"%#",actualNumber);
[textField setText:[currencyFormatter stringFromNumber:actualNumber]];
[mstring release];
}
//always return no since we are manually changing the text field
return NO;
}
else
{
return YES;
}
}
and This is the initialization
NSLocale *paklocal = [[[NSLocale alloc] initWithLocaleIdentifier:#"en_PAK"] autorelease];
currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[currencyFormatter setMaximumFractionDigits:0];
[currencyFormatter setLocale:paklocal];
NSMutableCharacterSet *numberSet = [[NSCharacterSet decimalDigitCharacterSet] mutableCopy];
[numberSet formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]];
nonNumberSet = [[numberSet invertedSet] retain];
[numberSet release];
I think you're having a problem because textField:shouldChangeCharactersInRange:replacementString: adds the currency symbol for [NSLocale currentLocale], which may be different from the locale used by currencyFormatter. In the simulator on my computer, it added $ (dollar) signs, to mstring, which were logically enough rejected by currencyFormatter.
When you construct paklocal, store it along with currencyFormatter and use it instead of [NSLocale currentLocale].
If you have further trouble with currencyFormatter, use NSLog to display the string you send into it.

How can i display the number in such a format?

I am displaying a number in textfield. Which displays the number as "1234" but i want to display it as in format of "1,234" if i enter another large number which displays as "12345" but i want to display it as "12,345" if i enter 123456 which has to display as "123,456" . How do I format this number in desired format?
-(void)clickDigit:(id)sender
{
NSString * str = (NSString *)[sender currentTitle];
NSLog(#"%#",currentVal);
if([str isEqualToString:#"."]&& !([currentVal rangeOfString:#"."].location == NSNotFound) )
{
return;
}
if ([display.text isEqualToString:#"0"])
{
currentVal = str;
[display setText:currentVal];
}
else if([currentVal isEqualToString:#"0"])
{
currentVal=str;
[display setText:currentVal];
}
else
{
if ([display.text length] <= MAXLENGTH)
{
currentVal = [currentVal stringByAppendingString:str];
NSLog(#"%#",currentVal);
[display setText:currentVal];
}
currentVal=display.text;
}
}
This is the code i am using to display the number in textfield.
EDIT: I Changed my code into the following but still don't get the number correctly formatted:
if ([display.text length] <= MAXLENGTH) {
currentVal = [currentVal stringByAppendingString:str];
NSNumberFormatter * myNumFormatter = [[NSNumberFormatter alloc] init];
[myNumFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *tempNum = [myNumFormatter numberFromString:currentVal];
NSLog(#"My number is %#",tempNum);
[display setText:[tempNum stringValue]];
currentVal=display.text;
}
You can do it like this:
int myInt = 12345;
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber *number = [NSNumber numberWithInt:myInt];
NSLog(#"%#", [formatter stringFromNumber:number]); // 12,345
Edit
You didn't implement this correctly, the key is to obtain the string representation of the number using [formatter stringFromNumber:number], but you didn't do that. So change your code into:
currentVal = [currentVal stringByAppendingString:str];
NSNumberFormatter * myNumFormatter = [[NSNumberFormatter alloc] init];
[myNumFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *tempNum = [myNumFormatter numberFromString:currentVal];
NSLog(#"My number is %#",tempNum);
[display setText:[myNumFormatter stringFromNumber:tempNum]]; // Change this line
currentVal=display.text;
NSLog(#"My formatted number is %#", currentVal);
First, read through the list of methods on the NSNumberFormatter reference page. After doing that, you'll probably realize that you need to use the -setHasThousandSeparators: method to turn on the thousand separators feature. You can also use the -setThousandSeparator: method to set a custom separator, though you probably won't need to do that.

NSNumberFormatter not allowing decimal input

If I enter a decimal point '.' into my UITextField, the number formatter called does not recognise the decimal point and continues as if the decimal point has not been entered. I.e If I entered 200.9, the decimal point would not show up in the textfield and the text of the textfield would be 2009.
I want to limit the number of digits after the decimal point to 2 as I believe I am doing below. Please can you tell me what I am doing to cause this?
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
BOOL isDeleting = [textField.text substringWithRange:range].length > string.length;
int index = [textFields indexOfObject:textField];
NSString *input;
if (isDeleting == NO)
input = [textField.text stringByAppendingString:string];
else {
NSMutableString *str = [textField.text mutableCopy];
[str deleteCharactersInRange:range];
input = [[str copy] autorelease];
[str release];
}
if ([input isEqualToString:#"£"] || ([input isEqualToString:#""] && index != 1)) {
[textField setText:#"£"];
}
else {
if (index != 1)
[textField setText:[self numberFormattedString:input]];
else
[textField setText:input];
}
return NO;
}
- (NSString *) numberFormattedString:(NSString *)str {
str = [str stringByReplacingOccurrencesOfString:#"£" withString:#""];
str = [str stringByReplacingOccurrencesOfString:#"," withString:#""];
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en-UK"];
[formatter setLocale:locale];
[locale release];
[formatter setAllowsFloats:YES];
[formatter setMaximumFractionDigits:3];
[formatter setMinimumFractionDigits:0];
[formatter setDecimalSeparator:#"."];
return [formatter stringFromNumber:[NSNumber numberWithFloat:[str floatValue]]];
}
TIA.
Let's say you enter the number 100 and then a decimal point. When numberFormattedString is called with the string £100., it's going to get rid of the £, and str will contain the string 100. which [str floatValue] converts to the float value 100, and finally your number formatter spits it back out as the string £100 without any decimal point. So basically [str floatValue] is killing your decimal point.
One solution is to check for when you get the decimal point as your replacement string in the text field delegate method, and skip calling numberFormattedString in that case. Then when the user enters the next digit, you can carry on calling numberFormattedString, and the conversion should happen correctly. You'll just have to make sure that the user can only enter one decimal point.
EDIT: I just realized that my suggested solution still won't work if you enter a 0 after the decimal point (e.g. 100.0), but I'm sure there is a minor tweak that you can figure out to solve that.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *numSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789."];
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
int charCount = [newString length];
if ([newString rangeOfCharacterFromSet:[numSet invertedSet]].location != NSNotFound
|| [string rangeOfString:#"."].location != NSNotFound
|| charCount > 15) {
return NO;
}
// if (charCount == 4 || charCount == 9 || charCount==13) {
// newString = [newString stringByAppendingString:#"."];
// }
NSLog(#"IN method");
textField.text = newString;
return NO;
}