UITextField 显示格式为没有小数的货币
Posted
技术标签:
【中文标题】UITextField 显示格式为没有小数的货币【英文标题】:UITextField display formatted as currency without decimal 【发布时间】:2016-12-21 05:46:16 【问题描述】:我正在尝试创建一个UITextField
,即使用户正在编辑,输入也会以货币格式永久显示。它应该像这样工作:
$0
用户类型 1
$1
用户类型 2
$12
用户类型 0
$120
用户类型 0
$1,200
用户类型 0
$12,000
我设法使用NumberFormatter
like 获得最终格式
textField.text = (numberFormatter.string(from: NSNumber(value: Int(textField.text!)!)))?.components(separatedBy: ".")[0]
但是一旦我在 textField 中格式化了文本,后续的输入就会导致如下错误:
$1,000
用户类型 0
$1,0000 //number formatter cannot recognise this as a format of currency
无论如何我可以操纵输入以允许用户只需要键入数字,但该值以正确的货币格式显示,带有符号加逗号 - 例如 $1,200,000。不管数字的多少——但逻辑上最多 10 位就足够了。
我当前的textFieldshouldChangeCharactersInRange
是这样的:
textField.text = numberFormatter.number(from: textField.text!)?.description
if(range.length == 1) //Backspace
if(textField.text?.characters.count == 1)
textField.text = "$0"
return false
return true
if(string.trimmingCharacters(in: CharacterSet.decimalDigits.inverted) == "")
textField.text = (numberFormatter.string(from: NSNumber(value: Int(textField.text!)!)))?.components(separatedBy: ".")[0]
return false
if(string == ".")
textField.text = (numberFormatter.string(from: NSNumber(value: Int(textField.text!)!)))?.components(separatedBy: ".")[0]
return false
textField.text = (numberFormatter.string(from: NSNumber(value: Int(textField.text!.append(string)!)!)))?.components(separatedBy: ".")[0]
return false
【问题讨论】:
如果有人能提供帮助我减少括号数量并使代码看起来更简洁而无需添加太多行的提示,我将不胜感激。 【参考方案1】:试试下面的代码
extension ViewController: UITextFieldDelegate
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
let text: NSString = (textField.text ?? "") as NSString
let finalString = text.replacingCharacters(in: range, with: string)
// 'currency' is a String extension that doews all the number styling
amountTextField.text = finalString.currency
// returning 'false' so that textfield will not be updated here, instead from styling extension
return false
extension String
var currency: String
// removing all characters from string before formatting
let stringWithoutSymbol = self.replacingOccurrences(of: "$", with: "")
let stringWithoutComma = stringWithoutSymbol.replacingOccurrences(of: ",", with: "")
let styler = NumberFormatter()
styler.minimumFractionDigits = 0
styler.maximumFractionDigits = 0
styler.currencySymbol = "$"
styler.numberStyle = .currency
if let result = NumberFormatter().number(from: stringWithoutComma)
return styler.string(from: result)!
return self
【讨论】:
这很聪明!我一直在考虑使用数字格式化程序来维护我的字符串,我完全错过了这种可能性 如果我们在中间输入数字,光标会移到末尾,有什么解决办法吗? 真的很干净,谢谢@Matt,有一个问题,有没有办法让最大值只有10位数? (包括货币符号和逗号)【参考方案2】:您可以使用 UITextField 的 leftView 和 rightView 属性,如下所示:这将只负责在输入字段的左侧显示“$”符号。
override func viewDidLoad()
super.viewDidLoad()
let label = UILabel(frame: CGRect(x :0,y :0,width :10,height: 10))
label.text = "$"
self.moneyTextField.leftViewMode = .always
self.moneyTextField.leftView = label
【讨论】:
实际上,我对货币符号没有太大问题,因为数字格式化程序会帮助处理它。我遇到麻烦的是逗号“,”。一旦用户输入超过 4 个数字,它将破坏格式【参考方案3】:// ViewController.swift
// TextfieldDemo
//
// Created by piyush sinroja on 21/12/16.
import UIKit
class ViewController: UIViewController, UITextFieldDelegate
@IBOutlet weak var txtDigit: UITextField!
var strDigit: String = String()
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let label = UILabel(frame: CGRect(x :0,y :0,width :10,height: 10))
label.text = "$"
self.txtDigit.leftViewMode = .always
self.txtDigit.leftView = label
txtDigit.layer.cornerRadius = 4.0
txtDigit.layer.masksToBounds = true
txtDigit.layer.borderColor = UIColor.lightGray.cgColor
txtDigit.layer.borderWidth = 1.0
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
func textFieldDidBeginEditing(_ textField: UITextField)
func textFieldDidEndEditing(_ textField: UITextField)
func textFieldShouldReturn(_ textField: UITextField) -> Bool
return true
func textField(_ textFieldToChange: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
if textFieldToChange == txtDigit
let aSet = NSCharacterSet(charactersIn:"0123456789").inverted
let compSepByCharInSet = string.components(separatedBy: aSet)
let numberFiltered = compSepByCharInSet.joined(separator: "")
if numberFiltered == ""
let new = txtDigit.text!
let fsf = new.substring(to: new.index(new.endIndex, offsetBy: -1))
let currentString = fsf
let findStr = commaStrSet(currentString: currentString)
txtDigit.text = findStr
return false
else
let currentString = (textFieldToChange.text! as NSString)
.replacingCharacters(in: range, with: string)
let findStr = commaStrSet(currentString: currentString)
txtDigit.text = findStr
return false
func commaStrSet(currentString: String) -> String
var replaceStr = currentString.replacingOccurrences(of: ",", with: "")
let length = replaceStr.characters.count
switch length
case 4:
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 1))
case 5:
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 2))
case 6:
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 1))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 5))
case 7:
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 2))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 5))
case 8:
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 1))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 4))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 7))
case 9:
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 2))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 5))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 8))
case 10:
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 1))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 4))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 7))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 10))
case 11,12,13,14,15:
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 1))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 4))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 7))
replaceStr.insert(",", at: replaceStr.index(replaceStr.startIndex, offsetBy: 10))
default:
break
return replaceStr
【讨论】:
我尝试了代码,似乎偏移量是错误的,我试图纠正它。感谢您的帮助。 没有它的工作正常。我只为你做了,你可以用你自己的逻辑 我尝试了另一种尝试使其与字符符号一起使用 - 以后需要改进。我仔细检查了一下,你的偏移量真的错了。返回值有“$,100”、“$1,00,000”和“$,10,00,00,000” @PiyushSinroja 你没有让亿万富翁有机会正确格式化他们的资产(又名“硬编码和幻数是邪恶的”)以上是关于UITextField 显示格式为没有小数的货币的主要内容,如果未能解决你的问题,请参考以下文章