For simple ATM style currency entry, I use the following code, which works quite well, if you use the UIKeyboardTypeNumberPad
option, which allows only digits and backspaces.
First set up an NSNumberFormatter
like this:
NSNumberFormatter* currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[currencyFormatter setMaximumSignificantDigits:9]; // max number of digits including ones after the decimal here
Then, use the following shouldChangeCharactersInRange code:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString* newText = [[[[textField.text stringByReplacingCharactersInRange:range withString:string] stringByReplacingOccurrencesOfString:currencyFormatter.currencySymbol withString:[NSString string]] stringByReplacingOccurrencesOfString:currencyFormatter.groupingSeparator withString:[NSString string]] stringByReplacingOccurrencesOfString:currencyFormatter.decimalSeparator withString:[NSString string]];
NSInteger newValue = [newText integerValue];
if ([newText length] == 0 || newValue == 0)
textField.text = nil;
else if ([newText length] > currencyFormatter.maximumSignificantDigits)
textField.text = textField.text;
else
textField.text = [currencyFormatter stringFromNumber:[NSNumber numberWithDouble:newValue / 100.0]];
return NO;
}
Most of the work is done in setting the newText
value; the proposed change is used but all non-digit characters put in by NSNumberFormatter
are taken out.
Then the first if test checks to see if the text is empty or all zeros (put there by the user or the formatter). If not, the next test makes sure that no more input except backspaces will be accepted if the number is already at the maximum number of digits.
The final else re-displays the number using the formatter so the user always sees something like $1,234.50
. Note that I use a $0.00
for the placeholder text with this code, so setting the text to nil shows the placeholder text.