2017-07-15 11 views
0

私はユーザー入力を通貨としてフォーマットしています。私は2つのラベルとテキストフィールドを含む非常に基本的なビューコントローラを持っています。シーンは次のようになります。通貨が小数点を受け入れるかどうかを検出する方法を教えてください。

Screenshot of view controller in Interface Builder

大手ラベルが値の前に記号が含まれている通貨の通貨記号を表示するように意図されます。後続ラベルは、値の後の記号を含む通貨の通貨記号を表示するためのものです。テキストフィールドは、入力されたテキストに合うように水平方向に伸縮し、後続の通貨記号は常に入力値に固定されます。未使用ラベルのtextプロパティはnilに設定されているため、非表示になります。

これまでのところ、すべて正常に動作します。別の通貨形式を使用するようにスキームのロケールを設定すると、ラベルに正しく入力されます。私は、次のコードで通貨記号の位置を検出しています:私は、いつでも、適用通貨の小数点区切りで、値のみを残して、テキストフィールド内の通貨記号を取り除く

internal static var currencySymbolPosition: CurrencySymbolPosition { 
    let currencyFormat = CFNumberFormatterGetFormat(CFNumberFormatterCreate(nil, Locale.current as CFLocale, .currencyStyle)) as NSString 
    let positiveNumberFormat = currencyFormat.components(separatedBy: ";")[0] as NSString 
    let currencySymbolLocation = positiveNumberFormat.range(of: "¤").location 
    let position: CurrencySymbolPosition = currencySymbolLocation == 0 ? .start : .end 
    return position 
} 

internal enum CurrencySymbolPosition { 
    case start 
    case end 
} 

。そのコードは次のようになります。

internal func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { 
    guard let text = textField.text else { return false } 
    guard let currencySymbol = formatter.currencySymbol else { return false } 
    guard let decimalSeparator = formatter.currencyDecimalSeparator else { return false } 
    guard let groupingSeparator = formatter.currencyGroupingSeparator else { return false } 
    guard let newText = (text as NSString?)?.replacingCharacters(in: range, with: string) else { return false } 
    let symbolsStripped = newText.replacingOccurrences(of: currencySymbol, with: "").replacingOccurrences(of: decimalSeparator, with: "").replacingOccurrences(of: groupingSeparator, with: "") 
    guard let integer = Int(symbolsStripped) else { return false } 
    let double = Double(integer)/100 
    guard let formatted = formatter.string(from: double as NSNumber) else { return false } 
    textField.text = formatted.replacingOccurrences(of: currencySymbol, with: "").trimmingCharacters(in: .whitespaces) 
    return false 
} 

私は、これが一部の通貨では機能しないという問題を抱えています。たとえば、円は小数点を使用しないので、let double = Double(integer)/100は機能しません。結果は常に0です。私は円の小数点記号を検出しようとしましたが、print(formatter.currencyDecimalSeparator)を使用して印刷するとXcodeは.を返します。 currencyDecimalSeparatorプロパティがNumberFormatterであるため、空の文字列が予想されていました。つまり、nilであってはなりません。私はcurrencyDecimalSeparatorを使って、正しい値を得るために100で割るべきかどうかを判断することを望んでいました。セパレータは分割を引き起こし、一方空のcurrencyDecimalSymbolは除算をスキップします。

このシーンは私が日本に地域を設定すると次のようになります。

Screenshot of iOS Simulator displaying currency format for Japan

これは私がチェコに地域を設定したときにシーンがどのように見えるかです:

Screenshot of iOS Simulator displaying currency format for Czech Republic

小数点を使用しない通貨を特定して、ユーザータイプとしてテキストフィールドの書式を正しく設定できる方法はありますか?

+0

なぜすべてを取り除くのが難しいのでしょうかそれだけですべてを戻そうとする句読点?通貨記号だけを削除してください。 – rmaddy

+0

@rmaddyテキストフィールドを使用タイプとしてフォーマットしているため、明示的に小数点を入力する必要はありません。ロケールで通貨の小数点記号を使用しない場合は、通貨を整数からフォーマットする必要があります。ロケールで通貨の小数点記号を使用している場合は、doubleからフォーマットする必要があります。このように、両方のタイプの通貨書式が適切に設定され、ユーザーは数字以外のものを入力する必要がありません。私は自分の意図をより明確にすることを願っています。 –

答えて

1

NumberFormattermaximumFractionDigitsminimumFractionDigitsのプロパティを調べて、ロケールで使用される小数点以下の桁数を確認します。

maximumFractionDigitsの値は、おそらく必要なものです。 maximumFractionDigitsの力で10を置くと、あなたの除数があります。円は0の値を持つ必要があります。10^0は当然1. maximumFractionDigitsが2であるUSDなどは、もちろん10の2を与えます。

+0

これは完全に機能しました。同じ書式の米ドルやその他の通貨の小数点を入力することができたので、小数点以下の書式を受け入れない通貨の整数だけを入力することができました。 –

関連する問題