Formating decimal on fly on a TextField iOS7 Xcode5 - ios7

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).

Related

how to put currency symbol while and after typing in UITextfield?

I have this stock market calculator that I am working on and I searched Apple documentation, the internet, here at StackOverFlow, but wasn't successful in finding the answer..
I have a UITextfield in which the user will input a currency value. What I want to implement is when the user is typing or at least after he finishes type the value the textfield would also display the currency symbol corresponding to the locale he is.
It's like a placeholder, but not the one we have in xcode, cause xcode's is there before we type and the one I want should be there while typing and after it. I could use a background image with the currency in it, but then I wouldn't be able to localize the app.
So if any one could help, I would appreciate.
Thanks in advance.
You have to use NSNumberFormatter to achieve this.
Try the following code, and by this, once you entered the values and when you end editing, the values will be formatted with current currency.
-(void)textFieldDidEndEditing:(UITextField *)textField {
NSNumberFormatter *currencyFormatter = [[[NSNumberFormatter alloc] init] autorelease];
[currencyFormatter setLocale:[NSLocale currentLocale]];
[currencyFormatter setMaximumFractionDigits:2];
[currencyFormatter setMinimumFractionDigits:2];
[currencyFormatter setAlwaysShowsDecimalSeparator:YES];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSNumber *someAmount = [NSNumber numberWithDouble:[textField.text doubleValue]];
NSString *string = [currencyFormatter stringFromNumber:someAmount];
textField.text = string;
}
The easiest way would be to put a label with right aligned text up against your text field, which would have left aligned text.
When the user starts to edit the textfield, set the currency symbol:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
self.currencyLabel.text = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencySymbol];
}
If you want to keep it as part of the text in the textField, it becomes a little more complicated as you need to keep them from deleting the symbol once you put it there:
// Set the currency symbol if the text field is blank when we start to edit.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if (textField.text.length == 0)
{
textField.text = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencySymbol];
}
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *newText = [textField.text stringByReplacingCharactersInRange:range withString:string];
// Make sure that the currency symbol is always at the beginning of the string:
if (![newText hasPrefix:[[NSLocale currentLocale] objectForKey:NSLocaleCurrencySymbol]])
{
return NO;
}
// Default:
return YES;
}
As #Aadhira points out, you should also be formatting the currency by using a number formatter since you are displaying it to the user.

NSNumberFormatter change decimal separator style

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
if (string.length == 0) {
return YES;
}
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber* candidateNumber;
NSString* candidateString = [textField.text stringByReplacingCharactersInRange:range withString:string];
range = NSMakeRange(0, [candidateString length]);
[numberFormatter getObjectValue:&candidateNumber forString:candidateString range:&range error:nil];
if (([candidateString length] > 0) && (candidateNumber == nil || range.length < [candidateString length])) {
return NO;
}
else
{
return YES;
}
Hi, with this code i can insert only decimal values in a textfield.
The decimal separator is a comma ","
How do I change it to a dot "." ?
Thanks
There is a little thing called Localization. Every language uses a different character as a decimal separator. Where English uses a decimal point, other languages use a comma (or other characters).
When you create a NSNumberFormatter it uses the system locale (NSLocale instance) to decide about the decimal separator (and grouping separator and other things).
If you want a fixed behavior, then just set a different locale using [NSNumberFormatter setLocale:]
Also note there is one special kind of locale
[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"] which defines a special locale which cannot be changed by user settings and is always the same.
In this case, using a NSNumberFormatter is not the best idea. This is one of the cases when you want to use a regular expression.

How to put comma and decimals in my UITextField dynamically?

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;
}

NSNumberFormatter only allowing 4 digits

Please can you tell me why my NSNumberFormatter is only letting me use 4 digits (i.e £2,222) instead of infinite digits?
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *input = [textField.text stringByAppendingString:string];
[textField setText:[self numberFormattedString:input]];
return NO;
}
- (NSString *) numberFormattedString:(NSString *)str {
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 setMaximumFractionDigits:3];
[formatter setMinimumFractionDigits:0];
return [formatter stringFromNumber:[NSNumber numberWithFloat:[str floatValue]]];
}
Edit--
When I type a fifth digit, having already 4 digits inside the UITextField, the textField's text is reset back to fifth digit typed alone.
E.G
I enter 1000 into the UITextField, I then enter a further digit of 5. As 5 is the fifth digit, the UITextField's text gets reset to the fifth digit alone. The UITextField now displays '5'.
TIA.
XcodeDev
The problem is that a comma is breaking [NSString floatValue]. When you get to entering the fifth digit, str ends up looking something like 1,0005, which floatValue converts to a value of 1 since it doesn't know how to deal with the comma and/or the fact that there are too many digits after it. Add this code
str = [str stringByReplacingOccurrencesOfString:#"," withString:#""];
as the first or second line of numberFormattedString and it will work.
What's probably happening is that as the user types, the formatter is inserting commas at the thousand marks. You aren't stripping those out when you do the reformatting like you are with the pound sign, so at some point the formatting function is being given a string like "1,000".
When you try to get the floatValue of that to convert it back into an NSNumber for reformatting, floatValue returns 1 because it can't parse commas.
Solution: add this extra line to your formatting function:
str = [str stringByReplacingOccurrencesOfString:#"," withString:#""];

UITextField - UIKeyboardTypeDecimalPad on iPad?

On the iPad...
textField.keyboardType = UIKeyboardTypeDecimalPad;
...just shows the regular keyboard, but starting on the numbers at the top (with lots of punctuation underneath).
But it's to type in a number. I only want the users to be able to type numbers and a decimal point, like UIKeyboardTypeDecimalPad does on the iPhone.
Is there any way to make the irrelevant keys go away and leave my user alone?
Setting a UITextField's keyboardType only makes it easier for a user to enter appropriate characters. Even on the iPhone, users can enter other characters via a hardware keyboard, or by pasting in a string.
Instead, implement UITextFieldDelegate's -textField:shouldChangeCharactersInRange:replacementString: to validate user input. You also probably don't really want to hardcode the digits 0-9 and a period. Users in some locales, for example, separate whole numbers from decimals with a comma:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *candidate = [[textField text] stringByReplacingCharactersInRange:range withString:string];
if (!candidate || [candidate length] < 1 || [candidate isEqualToString:#""])
{
return YES;
}
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:candidate];
if (!number || [number isEqualToNumber:[NSDecimalNumber notANumber]])
{
return NO;
}
return YES;
}
Alternately, you might perform validation when the user finishes entering text, in –textFieldShouldReturn:, – textFieldShouldEndEditing:, or – textFieldDidEndEditing: as desired.
This is not necessarily a foolproof solution, but it matched my needs and might be helpful to others. The concern would be that the number chars are hardcoded. I'm not sure of locales that use other numbers chars, but they can be added as needed.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *candidate = [[textField text] stringByReplacingCharactersInRange:range withString:string];
// Ensure that the local decimal seperator is used max 1 time
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
NSString *decimalSymbol = [formatter decimalSeparator];
if ([candidate componentsSeparatedByString:decimalSymbol].count > 2) return NO;
// Ensure that all the characters used are number characters or decimal seperator
NSString *validChars = [NSString stringWithFormat:#"0123456789%#", decimalSymbol];
if ([candidate stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:validChars]].length) return NO;
return YES;
}
I know this question has been inactive for quite a while, but this might help somebody out there.
You can try implementing this one https://github.com/azu/NumericKeypad. The coder implemented his own number pad buy subclassing the UITextField
Link this up to your textField's editingChanged method. You can edit the characters around as you feel the need to.
- (IBAction)numberValidator:(id)sender {
NSMutableString *txt1 = [[NSMutableString alloc] initWithString:_numbersOnlyField.text];
for (unsigned int i = 0; i < [txt1 length]; i++) {
NSString *character = [[NSString alloc] initWithFormat:#"%C", [txt1 characterAtIndex:i]];
// Erase any characters you don't like, but you don't feel the user needs to be alerted about
else if ([character isEqualToString:#" "]){
[txt1 deleteCharactersInRange:NSMakeRange(i, 1)];
_numbersOnlyField.text = [[NSString alloc] initWithString:txt1];
}
// Alert the user that they shouldn't enter anything besides numbers
if ([character integerValue] == 0 && ![character isEqualToString:#"0"]) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle: #"Numbers only please!"
message: #"Please only enter numbers in the \"<your text field's name here>\" text field"
delegate: nil
cancelButtonTitle:#"Sorry..."
otherButtonTitles:nil];
[alert show];
[txt1 deleteCharactersInRange:NSMakeRange(i, 1)];
_numbersOnlyField.text = [[NSString alloc] initWithString:txt1];
}
}
}
You can also do it programmatically through the UIControlEventValueChanged method.
This is just a solution I came up with myself and I definitely don't consider myself a professional, so there might be some flaws I'm overlooking, but this works pretty well for me.