Changing iOS textfield on the fly to show currency - ios

I have a UITextField that needs to show some currency data. The idea is that it should always show the formatted number with the $ symbol.
This is the code that I am using currently :
- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)string {
[self performSelector:#selector(timeToSearchForStuff:) withObject:textField afterDelay:0.3];
return YES;
}
- (void)timeToSearchForStuff:(UITextField*)textField
{
if (textField.text.length == 0) {
textField.text = #"$";
}
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setMaximumFractionDigits:0];
[numberFormatter setMinimumFractionDigits:0];
NSLocale *priceLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_AU"] ;
[numberFormatter setLocale:priceLocale];
long long inuy =[[numberFormatter numberFromString:textField.text]integerValue];
NSLog(#"starteo");
NSLog(#"inuy :: %lld", inuy);
NSString *formattedString =[numberFormatter stringFromNumber:[NSNumber numberWithLong:inuy]];
NSLog(#"chupacabra3 :: %#", formattedString);
self.textField.text = formattedString;
}
This works fine until I type more than 4 digits, if I type the 5th digit, the textfield goes to zero.
If I just log the value, it performs ok, but if i set the text on 5th digit, it again goes to zero.
Need some help on what is going wrong here. Guide me in the right direction.
Thanks.

change this condintion
if (textField.text.length == 0) {
textField.text = #"$";
}
with this
if (textField.text.length == 0) {
textField.text = #"$";
} else {
[textField setText:[textField.text stringByReplacingOccurrencesOfString:#"," withString:#""]];
}

Related

Check if an NSString is a double [duplicate]

This question already has an answer here:
parsing NSString to Double
(1 answer)
Closed 7 years ago.
How do I check if a UITextField's text is a double or not?
Simple validation required, if the entered textfield value is a valid double value or not?
Valid double values: 1.00, 1.01 or 1.00001
Invalid double values: .0.1, .001.11, 1.0.1 or 1...0 etc.
mytxtfield.text=#"12.00"; //ok
mytxtfield.text=#"1.2..0"; // is invalid and so on
EDIT: My answer that works thanx sahzad ali
//------------
-(BOOL)isvalidDouble:(NSString*)txtstring
{
NSArray *dotSeparratedArray = [txtstring componentsSeparatedByString:#"."];
NSInteger count=[dotSeparratedArray count];
count=count-1;
if(count >1)
{
return TRUE ; //invalid
}
return FALSE; //valid
}
You can limit user from entering multiple dots or you can use same logic in your TextFieldDidEndEditing method. If componentsSeparatedByString returns greater than 2 it means there are multiple dots.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *myString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSArray *dotSeparratedArray = [myString componentsSeparatedByString:#"."];
if([dotSeparratedArray count] >= 2)
{
NSString *string1=[NSString stringWithFormat:#"%#",[dotSeparratedArray objectAtIndex:1]];
return !([string1 length]>1);
}
return YES;
}
I don't know whether or not this will serve your purposes, but you could use NSNumberFormatter and customize it to your needs:
NSNumberFormatter *myFormatter = [[NSNumberFormatter alloc] init];
[myFormatter setFormatWidth:7];
[myFormatter setPaddingCharacter:#"0"];
[myFormatter setMinimumSignificantDigits:0];
[myFormatter setMinimum:#0];
[myFormatter setMaximum:#9999999];
[myClientIDTextField setFormatter:myFormatter];

Format a UITextField for currency

I have a UITextField on my aplication that receives only numeric input from the user. This numeric input represents currency and have the default value of 0.00.
I would like to create something like a mask to format the UITextField as the user enter the numbers. For example:
9 becomes $0,09
99 becomes $0,99
999 becomes $999,99
The code below works great, but as I'm using integer and float values the app will eventually display wrong values afeter a certain point. For example:
999999999 becomes 100000000
That happens because flot and integer aren't precise enough and NSDEcimalNumber should be used. The point is that I can't figure out how to replace my integers and float values to NSDecimalNumber ones.
Does anyone could give me a hand to solve this? I spend some time searching the web for a solution but didn't find that suits my needs and tons of people with the same problem.
Heres the code:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField.tag == 1){
NSString *cleanCentString = [[textField.text componentsSeparatedByCharactersInSet: [[NSCharacterSet decimalDigitCharacterSet] invertedSet]] componentsJoinedByString:#""];
NSInteger centValue= cleanCentString.integerValue;
if (string.length > 0)
{
centValue = centValue * 10 + string.integerValue;
}
else
{
centValue = centValue / 10;
}
NSNumber *formatedValue;
formatedValue = [[NSNumber alloc] initWithFloat:(float)centValue / 100.0f];
NSNumberFormatter *_currencyFormatter = [[NSNumberFormatter alloc] init];
[_currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
textField.text = [_currencyFormatter stringFromNumber:formatedValue];
return NO;
}
if (textField.tag == 2){
// Nothing for now
}
return YES;
}
Implement UITextFieldDelegate and add next methods:
Swift:
let currencySign = "$"
// Adds $ before the text, e.g. "1" -> "$1" and allows "." and ","
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
var value = textField.text
var newString = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
var components = newString.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "1234567890,.").invertedSet)
var decimalString = "".join(components) as NSString
var length = decimalString.length
if length > 0 {
value = "\(currencySign)\(decimalString)"
}
else {
value = ""
}
textField.text = value
}
// Formats final value using current locale, e.g. "130,50" -> "$130", "120.70" -> "$120.70", "5" -> "$5.00"
func textFieldDidEndEditing(textField: UITextField) {
var value = textField.text
var components = value.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "1234567890,.").invertedSet)
var decimalString = "".join(components) as NSString
let number = NSDecimalNumber(string: decimalString, locale:NSLocale.currentLocale())
var formatter = NSNumberFormatter()
formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
formatter.locale = NSLocale.currentLocale()
if let formatedValue = formatter.stringFromNumber(number) {
textField.text = formatedValue
}
else {
textField.text = ""
}
}
You can convert integer or double/float value to string by following:
NSString *str = [#(myInt) stringValue];
NSString *str1 = [[NSNumber numberWithFloat:myFloat] stringValue];
After that you can convert string to NSDecimalNumber by many ways. Like:
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:#"100.1"];
NSLog(#"%#", number);
NSDecimalNumber *num = [NSDecimalNumber decimalNumberWithString:#"100.1" locale:NSLocale.currentLocale];
NSLog(#"%#",num);
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setLocale:[NSLocale currentLocale]];
NSLog(#"%#", [formatter stringFromNumber:number]);
NSNumberFormatter will help you with the right formatting. Please read apples page for NSDecimalNumber and NSNumberFormatter.
NSNumberFormatter contains a section named"Configuring the Format of Currency". I didn't try it, but it seems something that can help you.
Let me know if this helps.. :)

Formating a single textfield so that it display is different to all the others

How would i set the currency in a text field to display it as a localized currency, with a leading 0. If someone types in 16.25 pence it would be formated as 0.1625£ respectively. I am using delegation and formating all text fields so only numbers can be passed in, this field should also be localized.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { // First, create the text that will end up in the input field if you'll return YES:
NSString *resultString = [textField.text stringByReplacingCharactersInRange:range withString:string];
// Now, validate the text and return NO if you don't like what it'll contain.
// You accomplish this by trying to convert it to a number and see if that worked.
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber* resultingNumber = [numberFormatter numberFromString:resultString];
//[numberFormatter release];
return resultingNumber != nil;
I do not want this to change, as it formats all my fields. Just want textField1 to have the relevant format,how would i go about doing this, i think it lies in viewdidload method and setting the text property to be localized to a floating point, but i cant seem to work out how to do it.
You can specify which textField you want to format in the delegate method above.
if (textField == textField1) {
// Do Something....
} else {
// Do whatever you want with the other text fields
}
For floating point formatting, use something like this -
[myTextField setText:[NSString stringWithFormat:#"%.2f", myFloat]];
(void)textFieldDidEndEditing:(UITextField *)textField
{
if (textfield1) {
NSString *txt = self.textfield1.text;
double num1 = [txt doubleValue];
double tCost = num1 /100;
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle: NSNumberFormatterCurrencyStyle];
NSString *numberAsString = [numberFormatter stringFromNumber:[NSNumber numberWithFloat:tCost]];
self.textfield1.text = [NSString stringWithFormat:#"%#",numberAsString];
}
}

Having trouble using NSNumberFormatter for currency conversion in iOS

I have a UITextField that receives numeric input from the user in my application. The values from this textfield then get converted into currency format using NSNumberFormatter within my shouldChangeCharactersInRange delegate method. When I enter the number "12345678", the number gets correctly converted to $123456.78 (the numbers are entered one digit at a time, and up to this point, everything works smoothly). However, when I enter another digit after this (e.g. 9), rather than displaying "1234567.89", the number "1234567.88" is displayed. If I enter another number after that, a totally different numbers after this (I'm using the number key pad in the application to enter the numbers. Here is the code that I have:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
modifiedValue = [formatter stringFromNumber:[NSNumber numberWithFloat:[modifiedValue floatValue]]];
textField.text = modifiedValue;
The line that causes this unusual conversion is this one:
modifiedValue = [formatter stringFromNumber:[NSNumber numberWithFloat:[modifiedValue floatValue]]];
Can anyone see why this is?
It's likely to be a rounding error when doing the string->float conversion. You shouldn't use floats when dealing with currency. You could use a NSDecimalNumber instead.
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
// Below 2 lines if converting from a "currency" string
NSNumber *modifiedNumber = [formatter numberFromString:modifiedValue]; // To convert from the currency string to a number object
NSDecimalNumber *decimal = [NSDecimalNumber decimalNumberWithDecimal:[modifiedNumber decimalValue]];
// OR the below line if converting from a non-currency string
NSDecimalNumber *decimal = [NSDecimalNumber decimalNumberWithString:modifiedValue];
modifiedValue = [formatter stringFromNumber:decimal]; // Convert the new decimal back to a currency string
You may also consider making the number formatter lenient - often helps with user entered data.
[formatter setLenient:YES];
When I'm running number conversions to currency, I usually run this code:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *text = _textField.text;
NSString *decimalSeperator = #".";
NSCharacterSet *charSet = nil;
NSString *numberChars = #"0123456789";
// the number formatter will only be instantiated once ...
static NSNumberFormatter *numberFormatter;
if (!numberFormatter)
{
[numberFormatter setLocale:[NSLocale currentLocale]];
numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
numberFormatter.maximumFractionDigits = 10;
numberFormatter.minimumFractionDigits = 0;
numberFormatter.decimalSeparator = decimalSeperator;
numberFormatter.usesGroupingSeparator = NO;
}
// create a character set of valid chars (numbers and optionally a decimal sign) ...
NSRange decimalRange = [text rangeOfString:decimalSeperator];
BOOL isDecimalNumber = (decimalRange.location != NSNotFound);
if (isDecimalNumber)
{
charSet = [NSCharacterSet characterSetWithCharactersInString:numberChars];
}
else
{
numberChars = [numberChars stringByAppendingString:decimalSeperator];
charSet = [NSCharacterSet characterSetWithCharactersInString:numberChars];
}
// remove amy characters from the string that are not a number or decimal sign ...
NSCharacterSet *invertedCharSet = [charSet invertedSet];
NSString *trimmedString = [string stringByTrimmingCharactersInSet:invertedCharSet];
text = [text stringByReplacingCharactersInRange:range withString:trimmedString];
// whenever a decimalSeperator is entered, we'll just update the textField.
// whenever other chars are entered, we'll calculate the new number and update the textField accordingly.
if ([string isEqualToString:decimalSeperator] == YES)
{
textField.text = text;
}
else
{
NSNumber *number = [numberFormatter numberFromString:text];
if (number == nil)
{
number = [NSNumber numberWithInt:0];
}
textField.text = isDecimalNumber ? text : [numberFormatter stringFromNumber:number];
}
return NO; // we return NO because we have manually edited the textField contents.
}
The link explaining this is Re-Apply currency formatting to a UITextField on a change event
Hope this works!

How to use NSNumberFormatter to insert blank space to NSString?

I want to write a UITextField that can auto format a number to bank number.
For example: Input 1234567890098765 will be automatically displayed as 1234 5678 9009 8765.
I'll use textFieldDelegate to do it, but I don't know how to use NSNumberFormatter.
How can I do it?
Using NSNumberFormatter is simple.
NSNumber *number = [NSNumber numberWithLongLong:1234567890098765];
NSNumberFormatter *formatter = [NSNumberFormatter new];
[formatter setUsesGroupingSeparator:YES];
[formatter setGroupingSize:3];
// [formatter setGroupingSeparator:#"\u00a0"];
NSString *string = [formatter stringFromNumber:number];
I deliberately commented the line that sets the formatter's grouping separator as it may be better to use the default one, which is provided by the user's locale (e.g. , in the USA, . in Germany and ' in Switzerland). Also please note that iOS doesn't use a space as a separator but a non-breaking space (U+00A0).
Try this :-
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *text = [textField text];
NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789\b"];
string = [string stringByReplacingOccurrencesOfString:#" " withString:#""];
if ([string rangeOfCharacterFromSet:[characterSet invertedSet]].location != NSNotFound) {
return NO;
}
text = [text stringByReplacingCharactersInRange:range withString:string];
text = [text stringByReplacingOccurrencesOfString:#" " withString:#""];
NSString *newString = #"";
while (text.length > 0) {
NSString *subString = [text substringToIndex:MIN(text.length, 4)];
newString = [newString stringByAppendingString:subString];
if (subString.length == 4) {
newString = [newString stringByAppendingString:#" "];
}
text = [text substringFromIndex:MIN(text.length, 4)];
}
newString = [newString stringByTrimmingCharactersInSet:[characterSet invertedSet]];
if (newString.length >= 20) {
return NO;
}
[textField setText:newString];
return NO;
}
Hope this helps you..
i have a c++ solution, maybe you can change your string to cstring and then change back
char s[50]={'\0'},ch[99]={'\0'};
int i,j,k,len;
printf("input a string:\n");
scanf("%s",s);
len=strlen(s);
k=0;
for(i=0;i<len;i+=4)
{
for(j=0;j<4;j++)
{
*(ch+k)=*(s+i+j);
k++;
}
*(ch+k)=' ';
k++;
}
printf("%s\n",ch);

Resources