如何动态格式化数字以在UITextField条目中包含逗号?

 北冥其名 发布于 2022-12-07 17:01

我希望UITextField在用户输入时动态地将逗号添加到我的数字条目中.

例如:123,45612,345,678,但不是这样123,45123,4567.

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

编辑:我也希望能够允许用户输入小数.

3 个回答
  • 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;
    }
    

    2022-12-11 02:09 回答
  • 对于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
    
        }
    

    2022-12-11 02:11 回答
  • 这是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"

    2022-12-11 02:13 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有