我的应用程序允许用户在UITextField
控件中输入数值(货币),但遗憾的是我希望的键盘布局不是内置选项之一,所以我不得不选择"数字和标点符号"选项. Interface Builder.这是IB中相应的对话窗口:
因此,当我的应用程序询问用户输入时,它显示以下内容:
哪个非常好,但请查看用户可用的所有额外密钥!人们可以很容易地输入"12; 56!" 在文本字段中,我假设我必须以某种方式验证.
所以我的问题是:如何验证输入的货币值UITextField
?
我有回答的冲动,因为这是我用Google搜索时看到的第一个条目,排名最高的答案不允许我输入货币.
我是德国人,在德国(以及许多其他国家)我们使用的,
是十进制分隔符.
我刚刚写了一个类似的方法,这就是我现在所拥有的.
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { static NSString *numbers = @"0123456789"; static NSString *numbersPeriod = @"01234567890."; static NSString *numbersComma = @"0123456789,"; //NSLog(@"%d %d %@", range.location, range.length, string); if (range.length > 0 && [string length] == 0) { // enable delete return YES; } NSString *symbol = [[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]; if (range.location == 0 && [string isEqualToString:symbol]) { // decimalseparator should not be first return NO; } NSCharacterSet *characterSet; NSRange separatorRange = [textField.text rangeOfString:symbol]; if (separatorRange.location == NSNotFound) { if ([symbol isEqualToString:@"."]) { characterSet = [[NSCharacterSet characterSetWithCharactersInString:numbersPeriod] invertedSet]; } else { characterSet = [[NSCharacterSet characterSetWithCharactersInString:numbersComma] invertedSet]; } } else { // allow 2 characters after the decimal separator if (range.location > (separatorRange.location + 2)) { return NO; } characterSet = [[NSCharacterSet characterSetWithCharactersInString:numbers] invertedSet]; } return ([[string stringByTrimmingCharactersInSet:characterSet] length] > 0); }
虽然你可以在NSNumberFormatter中使用putz,但我发现除了0-9之外的任何东西都更容易.
这对我很有用:
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSCharacterSet *nonNumberSet = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet];return ([string stringByTrimmingCharactersInSet:nonNumberSet].length > 0);}
如果用户想要删除输入的数字呢?
3> drewish..:我发现这是一种相对干净的方法.我没有用非美国货币测试它,但由于它使用了NSNumberFormatter的属性,我相信它应该正确处理它们.
首先在某个地方设置格式化程序:
formatter = [NSNumberFormatter new]; [formatter setNumberStyle: NSNumberFormatterCurrencyStyle]; [formatter setLenient:YES]; [formatter setGeneratesDecimalNumbers:YES];使用格式化程序解析和重新格式化其输入.它还可以在添加和删除数字时处理数字的移位.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSString *replaced = [textField.text stringByReplacingCharactersInRange:range withString:string]; NSDecimalNumber *amount = (NSDecimalNumber*) [formatter numberFromString:replaced]; if (amount == nil) { // Something screwed up the parsing. Probably an alpha character. return NO; } // If the field is empty (the initial case) the number should be shifted to // start in the right most decimal place. short powerOf10 = 0; if ([textField.text isEqualToString:@""]) { powerOf10 = -formatter.maximumFractionDigits; } // If the edit point is to the right of the decimal point we need to do // some shifting. else if (range.location + formatter.maximumFractionDigits >= textField.text.length) { // If there's a range of text selected, it'll delete part of the number // so shift it back to the right. if (range.length) { powerOf10 = -range.length; } // Otherwise they're adding this many characters so shift left. else { powerOf10 = [string length]; } } amount = [amount decimalNumberByMultiplyingByPowerOf10:powerOf10]; // Replace the value and then cancel this change. textField.text = [formatter stringFromNumber:amount]; return NO; }
非常感谢.为什么不能找到像这样的可用代码更容易??????
4> Marc Novakow..:也许你可以
UITextFieldDelegate
在控件上附加一个并实现textField:shouldChangeCharactersInRange:replacementString:
它.这样,如果它看到你在字段中不想要的任何字符,它就可以拒绝它们.
5> Matt Gallagh..:结合
textField:shouldChangeCharactersInRange:replacementString:
Marc提出的建议,你应该通过NSNumberFormatter
使用a 传递文本NSNumberFormatterCurrencyStyle
.这将处理货币格式的怪癖并处理特定于语言环境的选项.如果你搜索它,iPhone文档中有一个"Cocoa的数据格式编程指南"部分.遗憾的是,这里的大部分UI信息都是特定于Mac OS X(在iPhone上无法运行),但它将向您展示如何使用格式化程序类.
6> 小智..:我发现shouldChangeCharactersInRange也会弹出弹出式键盘,退格键和"完成"按钮.我发现如果我处理了0个长度字符串并允许控制字符,它工作正常.
我不喜欢使用NSNumberFormatter,因为它坚持在用户编辑时所有阶段的数字都是格式良好的,如果你想要在数字中暂时有两个小数点,直到你删除它可能会令人愤怒那个错误的地方.
这是我使用的代码:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if ([string length] < 1) // non-visible characters are okay return YES; if ([string stringByTrimmingCharactersInSet:[NSCharacterSet controlCharacterSet]].length == 0) return YES; return ([string stringByTrimmingCharactersInSet:[self.characterSet invertedSet]].length > 0); }self.characterSet保存可接受的字符,我使用此方法为货币创建它:
- (NSCharacterSet *)createCurrencyCharacterSet { NSLocale *locale = [NSLocale currentLocale]; NSMutableCharacterSet *currencySet = [NSMutableCharacterSet decimalDigitCharacterSet]; [currencySet addCharactersInString:@"-"]; // negative symbol, can't find a localised version [currencySet addCharactersInString:[locale objectForKey:NSLocaleCurrencySymbol]]; [currencySet addCharactersInString:[locale objectForKey:NSLocaleGroupingSeparator]]; [currencySet addCharactersInString:[locale objectForKey:NSLocaleDecimalSeparator]]; return [[currencySet copy] autorelease]; }有些不愉快的代码
[[currencySet copy] autorelease]
返回一个不可变的NSCharacterSet.使用
[NSCharacterSet decimalDigitCharacterSet]
还包括印度语和阿拉伯语等效字符,希望这意味着人们使用这些语言可以使用他们的字母数字来输入数字.仍然有必要检查NSNumberFormatter是否可以解析用户的输入并在不能的情况下发出警报; 尽管如此,当只能输入合法字符时,它会带来更好的体验.
7> Thomas Tempe..:我一直看到人们在实现shouldChangeCharactersInRange时不知道如何正确地确定结果字符串.
如果您返回YES,您将获得输入的新文本:
NSString *newText = [textField.text stringByReplacingCharactersInRange:range withString:string];获得此新文本后,可以轻松检查该文本是否为有效数字,并相应地返回YES或NO.
请记住,如果用户尝试使用带光标键的蓝牙键盘或使用高级键盘编辑字符串,则所有其他解决方案(例如此处显示的那些,其中一个检查"字符串"的长度等)可能无法正常工作编辑功能(选择,剪切,粘贴).