你如何dynamic地格式化一个数字在UITextField条目中有逗号?

我想在用户input时将逗号dynamic添加到我的数字UITextField条目中。

例如: 123,456123,45 ,但不是这样123,45123,4567

在用户在Objective-C中input数字时,如何自动附加逗号?

编辑:我也想能够让用户input小数。

而不是在shouldChangeCharactersInRange:自行插入逗号,您可以使用NSNumberFormatterDecimalStyle来处理逗号格式。 即使它被称为“十进制”样式,它也会插入逗号来适当地将数字分组到千位数中。

注意:为了简化问题,我假设您只想让文本字段接受数字条目,并且还会添加逻辑来将用户的input限制为数字。

编辑:我已经更新的代码来处理小数也按照OP的请求。

要在每个字符条目中使用NSNumberFormatterDecimalStyle的格式,请尝试将其添加到您的shouldChangeCharactersInRange: delegate方法中:

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

使用分组属性格式化数字,如下所示。

 NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; [numberFormatter setGroupingSeparator:@","]; [numberFormatter setGroupingSize:3]; [numberFormatter setDecimalSeparator:@"."]; [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; [numberFormatter setMaximumFractionDigits:3]; [numberFormatter setMinimumFractionDigits:3]; 

上面代码的输出是

 1,234,567.850 

这里是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 // eg "," 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 == "" { // pressed Backspace key totalTextWithoutGroupingSeparators.characters.removeLast() } if let numberWithoutGroupingSeparator = formatter.number(from: totalTextWithoutGroupingSeparators), let formattedText = formatter.string(from: numberWithoutGroupingSeparator) { textField.text = formattedText return false } } } return true } 

这种方法的一大优点是它使用当前语言环境(区域)中定义的分组分隔符,因为不是每个人都使用逗号作为分组分隔符。

使用0,退格,但是,我再次没有用小数testing它。 如果你使用小数来处理,你可以自由地增强这个代码。

例子:

  • input:“2” – >“2”
  • input:“3” – >“23”
  • input:“6” – >“236”
  • input:“7” – >“2,367”
  • input:“0”3次 – >“2,367,000”
  • 退格 – >“236,700”

也从0开始工作:

  • input:“0” – >“0”
  • input:“2” – >“2”

使用UITextFieldDelegate方法:(您的视图控制器需要是文本字段的委托)

 -(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 

当一个字符被添加到textField时,它会调用这个方法。 然后,您可以在任何地方插入逗号。

注意:人们可以将文本粘贴到文本框中,删除值,移动光标等,这样您就有很多testing需要考虑。

这里有很多类似的问题,例如, 如何在我的UITextField中dynamic地添加逗号和小数?

在逗号分隔的UITextfield自动build议

等等

有风的请记住,逗号应该得到添加到号码本身,而不是像用户必须input它们。

第一

 // Add a "textFieldDidChange" notification method to the text field control. [textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; 

你必须改变自己改变文本。 而将添加逗号的代码是

 -(void) textFieldDidChange { NSNumberFormatter *formatter = [NSNumberFormatter new]; [formatter setNumberStyle:NSNumberFormatterDecimalStyle]; // this line is important! NSString *formatted = [formatter stringFromNumber:[NSNumber numberWithInteger:2000000]]; NSLog(@"the Formatted String is %@",formatted); textField.text = formatted; } 

编辑见林赛斯科特的答案更新,正确的版本。

这是基于Lindsey Scott之前的回答,但更新为小数点后input的0:

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (textField == _questionPoolNameTextField) { return YES; } //For 0's after the decimal point: if ([string isEqualToString:@"0"] && (0 <= (int)[textField.text rangeOfString:@"."].location)) { if ([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)) { NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; [numberFormatter setGroupingSeparator:@","]; [numberFormatter setGroupingSize:3]; [numberFormatter setDecimalSeparator:@"."]; [numberFormatter setMaximumFractionDigits:20]; [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; // 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 = [numberFormatter numberFromString:numberWithoutCommas]; NSString *formattedString = [numberFormatter stringFromNumber:number]; // If the last entry was a decimal at the end of the // 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; } 

对于Lyndsey Scott的 Swift 3.0版的回答 :

  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?.length { formattedString = formattedString?.appending(".") } textField.text = formattedString } else { textField.text = nil } } return false }