我希望UITextField
在用户输入时动态地将逗号添加到我的数字条目中.
例如:123,456
和12,345,678
,但不是这样123,45
或123,4567
.
当用户在Objective-C中键入数字时,如何自动附加逗号?
编辑:我也希望能够允许用户输入小数.
shouldChangeCharactersInRange:
您可以使用a NSNumberFormatterDecimalStyle
来处理逗号格式,而不是自己插入逗号.即使它被称为"十进制"样式,它也会插入逗号以适当地将数字组合成千位数字.
注意:为了简化问题,我假设您只希望文本字段接受数字条目,我还将添加逻辑以限制用户对数字的输入.
编辑:我已根据OP的请求更新了代码以处理小数.
要NSNumberFormatterDecimalStyle
在每个字符条目上使用格式,请尝试将其添加到shouldChangeCharactersInRange:
委托方法:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (([string isEqualToString:@"0"] || [string isEqualToString:@""]) && [textField.text rangeOfString:@"."].location < range.location) { return YES; } // First check whether the replacement string's numeric... NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet]; NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""]; bool isNumeric = [string isEqualToString:filtered]; // Then if the replacement string's numeric, or if it's // a backspace, or if it's a decimal point and the text // field doesn't already contain a decimal point, // reformat the new complete number using // NSNumberFormatterDecimalStyle if (isNumeric || [string isEqualToString:@""] || ([string isEqualToString:@"."] && [textField.text rangeOfString:@"."].location == NSNotFound)) { // Create the decimal style formatter NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; [formatter setNumberStyle:NSNumberFormatterDecimalStyle]; [formatter setMaximumFractionDigits:10]; // Combine the new text with the old; then remove any // commas from the textField before formatting NSString *combinedText = [textField.text stringByReplacingCharactersInRange:range withString:string]; NSString *numberWithoutCommas = [combinedText stringByReplacingOccurrencesOfString:@"," withString:@""]; NSNumber *number = [formatter numberFromString:numberWithoutCommas]; NSString *formattedString = [formatter stringFromNumber:number]; // If the last entry was a decimal or a zero after a decimal, // re-add it here because the formatter will naturally remove // it. if ([string isEqualToString:@"."] && range.location == textField.text.length) { formattedString = [formattedString stringByAppendingString:@"."]; } textField.text = formattedString; } // Return no, because either the replacement string is not // valid or it is and the textfield has already been updated // accordingly return NO; }
对于Swift 4.0版本的Lyndsey Scott的回答:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { if ((string == "0" || string == "") && (textField.text! as NSString).range(of: ".").location < range.location) { return true } // First check whether the replacement string's numeric... let cs = NSCharacterSet(charactersIn: "0123456789.").inverted let filtered = string.components(separatedBy: cs) let component = filtered.joined(separator: "") let isNumeric = string == component // Then if the replacement string's numeric, or if it's // a backspace, or if it's a decimal point and the text // field doesn't already contain a decimal point, // reformat the new complete number using if isNumeric { let formatter = NumberFormatter() formatter.numberStyle = .decimal formatter.maximumFractionDigits = 8 // Combine the new text with the old; then remove any // commas from the textField before formatting let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string) let numberWithOutCommas = newString.replacingOccurrences(of: ",", with: "") let number = formatter.number(from: numberWithOutCommas) if number != nil { var formattedString = formatter.string(from: number!) // If the last entry was a decimal or a zero after a decimal, // re-add it here because the formatter will naturally remove // it. if string == "." && range.location == textField.text?.count { formattedString = formattedString?.appending(".") } textField.text = formattedString } else { textField.text = nil } } return false }
这是Swift 3中的一个版本.我用它来表示整数,我没有用十进制数来检查.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // Uses the number format corresponding to your Locale let formatter = NumberFormatter() formatter.numberStyle = .decimal formatter.locale = Locale.current formatter.maximumFractionDigits = 0 // Uses the grouping separator corresponding to your Locale // e.g. "," in the US, a space in France, and so on if let groupingSeparator = formatter.groupingSeparator { if string == groupingSeparator { return true } if let textWithoutGroupingSeparator = textField.text?.replacingOccurrences(of: groupingSeparator, with: "") { var totalTextWithoutGroupingSeparators = textWithoutGroupingSeparator + string if string.isEmpty { // pressed Backspace key totalTextWithoutGroupingSeparators.removeLast() } if let numberWithoutGroupingSeparator = formatter.number(from: totalTextWithoutGroupingSeparators), let formattedText = formatter.string(from: numberWithoutGroupingSeparator) { textField.text = formattedText return false } } } return true }
此方法的最大优点是它使用当前语言环境(区域)中定义的分组分隔符,因为并非每个人都使用逗号作为分组分隔符.
使用0,退格键,但是,我再次没有使用小数测试它.如果您使用小数进行处理,则可以自由地增强此代码.
例子:
输入:"2" - >"2"
输入:"3" - >"23"
输入:"6" - >"236"
输入:"7" - >"2,367"
输入:"0"3次 - >"2,367,000"
退格 - >"236,700"
从0起作用:
输入:"0" - >"0"
输入:"2" - >"2"