Форматирование валюты - Swift - PullRequest
1 голос
/ 18 апреля 2019

Я ищу средство форматирования валюты текстового поля, которое удовлетворяет следующим критериям:

  1. Оно должно быть отформатировано (через запятую) , поскольку я набираю
  2. Следует разрешить регулярное выражение для (2)
  3. Когда мы вырезаем, курсор должен оставаться на том же месте
  4. Когда мы вводим середину валюты, курсор не должен сдвигаться влево.
  5. Он должен поддерживать локализацию (запятые и точки) в регулярном выражении.

У меня естьпопробовал множество решений:

  1. Использование NSCharacterSet (Это самое близкое, но здесь не выполняется регулярное выражение из-за обмена . и , во время локализации, также мы использовали .decimal введите здесь, чтобы избежать $ в textField)

    class func checkTextField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let textBeforeEditing = textField.text else {
            return true
        }
        if ((string == "0" || string == "") && (textField.text! as NSString).range(of: ".").location < range.location) {
            return true
        }
        var currentPosition = 0
        if let selectedRange = textField.selectedTextRange {
            currentPosition = textField.offset(from: textField.beginningOfDocument, to: string == "" ? selectedRange.end : selectedRange.start)
        }
        let allowedCharacterSet = NSCharacterSet(charactersIn: "0123456789.").inverted
        let filtered = string.components(separatedBy: allowedCharacterSet)
        let component = filtered.joined(separator: "")
        let isNumeric = string.replacingOccurrences(of: ",", with: "") == component
        var textFieldString : String = ""
        var numberWithoutCommas : String = ""
        guard isNumeric else {
            return false
        }
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        textFieldString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
        numberWithoutCommas = textFieldString.replacingOccurrences(of: ",", with: "")
        let formattedNumberWithoutCommas = formatter.number(from: numberWithoutCommas)
        guard let formattedNumber = formattedNumberWithoutCommas, var formattedString = formatter.string(from: formattedNumber) else {
            textField.text = nil
            return false
        }
        if string == "." && range.location == textField.text?.count {
            formattedString = formattedString.appending(".")
        }
        textField.text = formattedString
        currentPosition = getCursorPositionForTextField(string: string, cursorPosition: currentPosition, formattedString: formattedString, textBeforeEditing: textBeforeEditing)
        handleTextFieldCursor(cursorPosition: currentPosition, textField: textField)
        return false
    }
    
  2. Используя NumberFormatter, но курсор сдвигается до конца при каждом вырезании / вставке

    extension String {
    
        func currencyInputFormatting() -> String {
    
            var number: NSNumber!
            let formatter = NumberFormatter()
            formatter.numberStyle = .currency
            formatter.maximumFractionDigits = 2
            formatter.minimumFractionDigits = 2
    
            var amountWithPrefix = self
    
            // remove from String: "$", ".", ","
            let regex = try! NSRegularExpression(pattern: "[^0-9]", options: .caseInsensitive)
            amountWithPrefix = regex.stringByReplacingMatches(in: amountWithPrefix, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count), withTemplate: "")
    
            let double = (amountWithPrefix as NSString).doubleValue
            number = NSNumber(value: (double / 100))
    
            guard number != 0 as NSNumber else {
                return ""
            }
    
            return formatter.string(from: number)!
        }
    }
    

Я потратил почти день или два, чтобы найти 100% работоспособное решение, но не смог Разрешить.Буду признателен за любую помощь

РЕДАКТИРОВАТЬ

Я подошел к решению с помощью ответа @ denis_lor , но все еще не смогдобиться обмена запятой с точкой.Вот мой обновленный код, я что-то упустил?Отлично работает с английским, но не с испанским.

class func checkTextField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let textBeforeEditing = textField.text else {
        return true
    }
    if ((string == "0" || string == "") && (textField.text! as NSString).range(of: "\(NSLocalizedString("core_decimal_separator_symbol", comment: ""))").location < range.location) {
        return true
    }
    var currentPosition = 0
    if let selectedRange = textField.selectedTextRange {
        currentPosition = textField.offset(from: textField.beginningOfDocument, to: string == "" ? selectedRange.end : selectedRange.start)
    }
    let allowedCharacterSet = NSCharacterSet(charactersIn: "0123456789\(NSLocalizedString("core_decimal_separator_symbol", comment: ""))").inverted
    let filtered = string.components(separatedBy: allowedCharacterSet)
    let component = filtered.joined(separator: "")
    let isNumeric = string.replacingOccurrences(of: NSLocalizedString("core_thousand_separator_symbol", comment: ""), with: "") == component
    var textFieldString : String = ""
    var numberWithoutCommas : String = ""
    guard isNumeric else {
        return false
    }
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    textFieldString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
    numberWithoutCommas = textFieldString.replacingOccurrences(of: NSLocalizedString("core_thousand_separator_symbol", comment: ""), with: "")
    let formattedNumberWithoutCommas = formatter.number(from: numberWithoutCommas)
    guard let formattedNumber = formattedNumberWithoutCommas, var formattedString = formatter.string(from: formattedNumber) else {
        textField.text = nil
        return false
    }
    if string == NSLocalizedString("core_decimal_separator_symbol", comment: "") && range.location == textField.text?.count {
        formattedString = formattedString.appending(NSLocalizedString("core_decimal_separator_symbol", comment: ""))
    }
    textField.text = formattedString
    currentPosition = getCursorPositionForTextField(string: string, cursorPosition: currentPosition, formattedString: formattedString, textBeforeEditing: textBeforeEditing)
    handleTextFieldCursor(cursorPosition: currentPosition, textField: textField)
    return false
}

1 Ответ

1 голос
/ 18 апреля 2019

Хорошо, так что, похоже, ваша проблема здесь может быть решена путем реализации первого решения вашего первого решения, когда вам нужно думать только о локализации , и ..Это легко, вы могли бы реализовать это разными способами, но важная часть заключается в том, что ваше приложение, например, локализовано, скажем, на два языка, которые обрабатывают десятичные и тысячи различных символов (предположим, в качестве примера, эти языки - английский и итальянский)):

  • [en] язык обрабатывает разделение десятичных дробей с , и тысячи с .
  • [it] язык обрабатывает разделение десятичных дробей с . и тысячи с ,

A) Что вы можете сделать, это создать файл Localizable.strings и затем локализовать ваш проект, скажем, на английском и итальянском, например.Для этого добавьте язык сюда.enter image description here

B) Затем перейдите к файлу Localizable.strings и localize для поддерживаемых языков (например, английского и итальянского), как на этом изображении, которое былосделано для немецкого и английского enter image description here

Теперь у вас будет две строки Localizable.string, одна для английского и одна для итальянского:

Localizable.строки (английский)

core_decimal_separator_symbol = ",";
core_thousand_separator_symbol = ".";

Localizable.strings (итальянский)

core_decimal_separator_symbol = ".";
core_thousand_separator_symbol = ",";

C) И в вашем коде везде, куда вам нужно обратиться,например, ваш символ десятичного разделителя , вместо того, чтобы писать его жестко, вы можете сделать что-то вроде:

removeDecimalSeparator = numberAsString.replacingOccurrences(of: NSLocalizedString("core_decimal_separator_symbol", comment: ""), with: "")

Так что всякий раз, когда ваше приложение локализовано на английский, например, этот кодбудет транслироваться в:

removeDecimalSeparator = numberAsString.replacingOccurrences(of: ",", with: "")

И когда ваше приложение будет локализовано, например, на итальянский, этот код будет транслироваться в:

removeDecimalSeparator = numberAsString.replacingOccurrences(of: ".", with: "")

В заключение:рассмотрим их в качестве примера, принимая во внимание Localizable.strings, которые мы имеем в этом ответе.Просто чтобы показать вам, как вы можете по-разному манипулировать некоторыми символами для разных языков, используя локализацию в своем приложении.

...