통화를 위해 Swift에서 NSNumberFormatter로 고군분투


87

사용자가 자신의 예산과 거래를 입력 할 수있는 예산 앱을 만들고 있습니다. 사용자가 별도의 텍스트 필드에서 펜스와 파운드를 모두 입력 할 수 있도록 허용하고 통화 기호와 함께 서식을 지정해야합니다. 현재 잘 작동하지만 현재는 GBP에서만 작동하므로 현지화하고 싶습니다. 저는 Objective C에서 Swift로 NSNumberFormatter 예제를 은폐하기 위해 고군분투하고 있습니다.

첫 번째 문제는 입력 필드의 자리 표시자를 사용자 위치에 맞게 설정해야한다는 사실입니다. 예 : 파운드와 펜스, 달러와 센트 등 ...

두 번째 문제는 10216 및 32와 같은 각 텍스트 필드에 입력 된 값을 형식화하고 사용자 위치에 맞는 통화 기호를 추가해야한다는 것입니다. 따라서 £ 10,216.32 또는 $ 10,216.32 등이됩니다.

또한 계산에 서식이 지정된 숫자의 결과를 사용해야합니다. 그렇다면 통화 기호에 문제가 발생하지 않고 문제없이 어떻게이 작업을 수행 할 수 있습니까?

어떤 도움이라도 대단히 감사하겠습니다.


2
작동하지 않는 코드의 예를 게시 할 수 있습니까?
NiñoScript 2014

답변:


207

다음은 Swift 3에서 사용하는 방법에 대한 예제입니다 . ( 편집 : Swift 4에서도 작동합니다.)

let price = 123.436 as NSNumber

let formatter = NumberFormatter()
formatter.numberStyle = .currency
// formatter.locale = NSLocale.currentLocale() // This is the default
// In Swift 4, this ^ has been renamed to simply NSLocale.current
formatter.string(from: price) // "$123.44"

formatter.locale = Locale(identifier: "es_CL")
formatter.string(from: price) // $123"

formatter.locale = Locale(identifier: "es_ES")
formatter.string(from: price) // "123,44 €"

다음은 Swift 2에서 사용하는 방법에 대한 이전 예제입니다.

let price = 123.436

let formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
// formatter.locale = NSLocale.currentLocale() // This is the default
formatter.stringFromNumber(price) // "$123.44"

formatter.locale = NSLocale(localeIdentifier: "es_CL")
formatter.stringFromNumber(price) // $123"

formatter.locale = NSLocale(localeIdentifier: "es_ES")
formatter.stringFromNumber(price) // "123,44 €"

감사. 나는 내 질문을 편집했고 더 구체적입니다.
user3746428 jul.

귀하가 제공 한 예를 기반으로, 내 프로그램에 숫자 형식을 구현하여 해당 비트가 정렬되었습니다. 이제 사용자 위치에 따라 텍스트 필드 자리 표시자를 설정하는 방법을 알아 내면됩니다.
user3746428 jul.

2
NSNumber로 캐스트 할 필요가 없습니다. 포맷터 메소드 func string (for obj : Any?)-> String ?. 당신은 사용할 필요가 그래서 string(for: price)대신string(from: price)
레오 버스들이시길

1
@LeoDabus 당신 말이 맞아요, 나는 그 방법에 대해 몰랐습니다. 내 대답을 편집 해야하는지 확실하지 않습니다. 내가 NumberFormatter의 API를 사용하고 암시 적으로 허용하기보다는 NSNumber를 사용하는 것에 대해 명시 적으로 생각하기 때문입니다. 안에 던지세요.
NiñoScript

formatter.string (from :)의 결과는 String (주석에 함축 된대로)이 아닌 선택적 String이므로 사용하기 전에 언 래핑해야합니다.
Ali Beadle 2017 년

25

스위프트 3 :

제공하는 솔루션을 찾고있는 경우 :

  • "5"= "$ 5"
  • "5.0"= "$ 5"
  • "5.00"= "$ 5"
  • "5.5"= "$ 5.50"
  • "5.50"= "$ 5.50"
  • "5.55"= "$ 5.55"
  • "5.234234"= "5.23"

다음을 사용하십시오 :

func cleanDollars(_ value: String?) -> String {
    guard value != nil else { return "$0.00" }
    let doubleValue = Double(value!) ?? 0.0
    let formatter = NumberFormatter()
    formatter.currencyCode = "USD"
    formatter.currencySymbol = "$"
    formatter.minimumFractionDigits = (value!.contains(".00")) ? 0 : 2
    formatter.maximumFractionDigits = 2
    formatter.numberStyle = .currencyAccounting
    return formatter.string(from: NSNumber(value: doubleValue)) ?? "$\(doubleValue)"
}

당신이 방법 포맷터 사용할 수있는 새로운의 NSNumber 객체를 초기화 할 필요가 없습니다 func string(for obj: Any?) -> String?대신string(from:)
레오 버스들이시길

19

@ NiñoScript에서 제공하는 솔루션도 확장으로 구현했습니다.

신장

// Create a string with currency formatting based on the device locale
//
extension Float {
    var asLocaleCurrency:String {
        var formatter = NSNumberFormatter()
        formatter.numberStyle = .CurrencyStyle
        formatter.locale = NSLocale.currentLocale()
        return formatter.stringFromNumber(self)!
    }
}

용법:

let amount = 100.07
let amountString = amount.asLocaleCurrency
print(amount.asLocaleCurrency())
// prints: "$100.07"

스위프트 3

    extension Float {
    var asLocaleCurrency:String {
        var formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.locale = Locale.current
        return formatter.string(from: self)!
    }
}

.. FlotingPoint 유형의 당신이 :) 방법 문자열을 (사용해야하는 방법의 NSNumber위한 나는 스위프트 3 확장을 게시 한 : 확장에서 스위프트 3 버전 문자열 (대한 부동 소수점을 확장해야한다
레오 버스들이시길

통화에 부동 유형을 사용하지 말고 십진수를 사용하십시오.
adnako

17

Xcode 11 • Swift 5.1

extension Locale {
    static let br = Locale(identifier: "pt_BR")
    static let us = Locale(identifier: "en_US")
    static let uk = Locale(identifier: "en_GB") // ISO Locale
}

extension NumberFormatter {
    convenience init(style: Style, locale: Locale = .current) {
        self.init()
        self.locale = locale
        numberStyle = style
    }
}

extension Formatter {
    static let currency = NumberFormatter(style: .currency)
    static let currencyUS = NumberFormatter(style: .currency, locale: .us)
    static let currencyBR = NumberFormatter(style: .currency, locale: .br)
}

extension Numeric {
    var currency: String { Formatter.currency.string(for: self) ?? "" }
    var currencyUS: String { Formatter.currencyUS.string(for: self) ?? "" }
    var currencyBR: String { Formatter.currencyBR.string(for: self) ?? "" }
}

let price = 1.99

print(Formatter.currency.locale)  // "en_US (current)\n"
print(price.currency)             // "$1.99\n"

Formatter.currency.locale = .br
print(price.currency)  // "R$1,99\n"

Formatter.currency.locale = .uk
print(price.currency)  // "£1.99\n"

print(price.currencyBR)  // "R$1,99\n"
print(price.currencyUS)  // "$1.99\n"

3
통화에 부동 유형을 사용하지 말고 십진수를 사용하십시오.
adnako


7

세부

  • Xcode 10.2.1 (10E1001), Swift 5

해결책

import Foundation

class CurrencyFormatter {
    static var outputFormatter = CurrencyFormatter.create()
    class func create(locale: Locale = Locale.current,
                      groupingSeparator: String? = nil,
                      decimalSeparator: String? = nil,
                      style: NumberFormatter.Style = NumberFormatter.Style.currency) -> NumberFormatter {
        let outputFormatter = NumberFormatter()
        outputFormatter.locale = locale
        outputFormatter.decimalSeparator = decimalSeparator ?? locale.decimalSeparator
        outputFormatter.groupingSeparator = groupingSeparator ?? locale.groupingSeparator
        outputFormatter.numberStyle = style
        return outputFormatter
    }
}

extension Numeric {
    func toCurrency(formatter: NumberFormatter = CurrencyFormatter.outputFormatter) -> String? {
        guard let num = self as? NSNumber else { return nil }
        var formatedSting = formatter.string(from: num)
        guard let locale = formatter.locale else { return formatedSting }
        if let separator = formatter.groupingSeparator, let localeValue = locale.groupingSeparator {
            formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator)
        }
        if let separator = formatter.decimalSeparator, let localeValue = locale.decimalSeparator {
            formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator)
        }
        return formatedSting
    }
}

용법

let price = 12423.42
print(price.toCurrency() ?? "")

CurrencyFormatter.outputFormatter = CurrencyFormatter.create(style: .currencyISOCode)
print(price.toCurrency() ?? "nil")

CurrencyFormatter.outputFormatter = CurrencyFormatter.create(locale: Locale(identifier: "es_ES"))
print(price.toCurrency() ?? "nil")

CurrencyFormatter.outputFormatter = CurrencyFormatter.create(locale: Locale(identifier: "de_DE"), groupingSeparator: " ", style: .currencyISOCode)
print(price.toCurrency() ?? "nil")

CurrencyFormatter.outputFormatter = CurrencyFormatter.create(groupingSeparator: "_", decimalSeparator: ".", style: .currencyPlural)
print(price.toCurrency() ?? "nil")

let formatter = CurrencyFormatter.create(locale: Locale(identifier: "de_DE"), groupingSeparator: " ", decimalSeparator: ",", style: .currencyPlural)
print(price.toCurrency(formatter: formatter) ?? "nil")

결과

$12,423.42
USD12,423.42
12.423,42 €
12 423,42 EUR
12_423.42 US dollars
12 423,42 Euro

3

@Michael Voccola의 답변에서 Swift 4로 업데이트되었습니다.

extension Double {
    var asLocaleCurrency: String {
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.locale = Locale.current

        let formattedString = formatter.string(from: self as NSNumber)
        return formattedString ?? ""
    }
}

참고 : force-unwraps, force-unwraps는 사악합니다.


2

Swift 4 TextField 구현

var value = 0    
currencyTextField.delegate = self

func numberFormatting(money: Int) -> String {
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.locale = .current
        return formatter.string(from: money as NSNumber)!
    }

currencyTextField.text = formatter.string(from: 50 as NSNumber)!

func textFieldDidEndEditing(_ textField: UITextField) {
    value = textField.text
    textField.text = numberFormatting(money: Int(textField.text!) ?? 0 as! Int)
}

func textFieldDidBeginEditing(_ textField: UITextField) {
    textField.text = value
}

0
extension Float {
    var convertAsLocaleCurrency :String {
        var formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.locale = Locale.current
        return formatter.string(from: self as NSNumber)!
    }
}

이것은 신속한 3.1 xcode 8.2.1에서 작동합니다.


이 코드 스 니펫은 환영하며 약간의 도움을 제공 할 수 있지만 문제를 해결하는 방법이유에 대한 설명포함되어 있으면 크게 개선 될 것 입니다. 지금 질문하는 사람뿐만 아니라 미래에 독자를 위해 질문에 답하고 있다는 것을 기억하십시오! 제발 편집 설명을 추가하고, 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을.
Toby Speight

통화에 부동 유형을 사용하지 말고 십진수를 사용하십시오.
adnako

0

스위프트 4

formatter.locale = Locale.current

로케일을 변경하려면 다음과 같이 할 수 있습니다.

formatter.locale = Locale.init(identifier: "id-ID") 

// 인도네시아 로케일의 로케일입니다. 휴대 전화 지역별로 사용하고자한다면 위의 Locale.current에 따라 사용하십시오.

//MARK:- Complete code
let formatter = NumberFormatter()
formatter.numberStyle = .currency
    if let formattedTipAmount = formatter.string(from: Int(newString)! as 
NSNumber) { 
       yourtextfield.text = formattedTipAmount
}

0

이 기능 추가

func addSeparateMarkForNumber(int: Int) -> String {
var string = ""
let formatter = NumberFormatter()
formatter.locale = Locale.current
formatter.numberStyle = .decimal
if let formattedTipAmount = formatter.string(from: int as NSNumber) {
    string = formattedTipAmount
}
return string
}

사용 :

let giaTri = value as! Int
myGuessTotalCorrect = addSeparateMarkForNumber(int: giaTri)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.