Swift 3 Десятичный, NSDecimal и NSDecimalNumber

Я пытаюсь использовать NumberFormatter с Swift 3 Decimal, но я смущен тем, как Decimal действительно реализуется. Проблема, с которой я сталкиваюсь, заключается в том, что Decimal является структурой, поэтому я должен привязать ее к NSDecimalNumber каждый раз, когда я хочу использовать форматтер, чего я бы хотел избежать.

let formatter = NumberFormatter()
formatter.numberStyle = .decimal
let decimal = Decimal(integerLiteral: 3)
let string = formatter.string(from: decimal as NSDecimalNumber)

Является ли идеальным обходным путем для реализации моего собственного расширения, которое принимает Decimal?

extension NumberFormatter {
    open func string(from number: Decimal) -> String? {
        return string(from: number as NSDecimalNumber)
    }
}

В более общем плане, каждый раз, когда мне нужно передать тип объекта, мне потребуется мост Decimal или написать дополнительные расширения?

ИЗМЕНИТЬ

Наверное, мне больше интересно узнать о NSDecimal Decimal и NSDecimalNumber в Swift 3. Мне совсем не ясно, что здесь происходит. Должен ли я заменить NSDecimalNumber на Decimal для Swift 3? Документы пишут:

Наложение Swift в структуру Foundation предоставляет структуру Decimal, которая соединяется с классом NSDecimalNumber. Тип десятичного значения предлагает ту же функциональность, что и ссылочный тип NSDecimalNumber, и эти два могут быть взаимозаменяемы в коде Swift, который взаимодействует с API Objective-C. Это поведение похоже на то, как Swift соединяет стандартные строковые, числовые и типы коллекций с соответствующими классами Foundation.

Вначале я думал, что Decimal был новым NSDecimalNumber как Error - это новый NSError, но теперь я не уверен. Это также говорит: "Тип десятичного значения предлагает ту же функциональность, что и ссылочный тип NSDecimalNumber` - это действительно так? Похоже, что я не могу получить практически одинаковые функциональные возможности (без предварительного согласования, конечно, это то, что они означают?). Я нашел несколько сообщений и немного информации здесь и там, но ничего такого убедительного. Кто-нибудь знает или понимает?

Мое приложение специально использует NSDecimalNumber для валюты и форматирования, поэтому округление и форматирование являются высокоприоритетными.

Ответы

Ответ 1

Я задал свой вопрос на совете быстрых пользователей и получил замечательный ответ, посмотрите здесь: https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20161219/004220.html

Текстовая версия ответа:

Swift 3 представил класс Decimal, который, поначалу, я думал, должен был "заменить" NSDecimalNumber в Swift, например Error - это новый NSError и т.д. Однако при дальнейшем расследовании мне не ясно, что это на самом деле дело. Похоже, что Swift 3 Decimal является скорее просто NSDecimal, но с некоторым мостом, поэтому при необходимости может использовать методы NSDecimalNumber. Мне интересно, должен ли я заменять NSDecimalNumber в моем приложении с помощью десятичного числа? Десятичная преемника NSDecimalNumber в Swift?

Decimal на самом деле является структурой, а не классом, и на самом деле это просто имя Swift для структуры NSDecimal в Objective-C. В Swift функции типа NSDecimalAdd отображаются как операторы на Decimal и используются для удовлетворения требований различных числовых протоколов, таких как SignedNumber.

Конечным результатом является то, что Decimal очень похож на Int или Double - это тип значения, который можно удобно использовать для выполнения всех видов математики. NSDecimalNumber, то эквивалентно NSNumber.

Так как мое приложение делает много форматирования, для него потребуется много кастинга между Decimal и NSDecimalNumber или добавлением расширений, поэтому я не думаю, что это было бы естественно/удобно без многих расширений. Планируется ли Swift планировать улучшение Decimal для более удобного использования с NumberFormatter или другими объектно-ориентированными API-интерфейсами? Надеюсь, я дал достаточно информации, чтобы ответить на мой вопрос.

Objective-C API, которые используют NSDecimalNumber, должны быть привязаны к Decimal, так же как NSString соединяется с String. Тем не менее, этот мост может не работать для методов категорий; вы можете открыть их для Swift, написав расширение на Decimal, которое отбрасывает self в NSDecimalNumber, а затем вызывает ваши методы Objective-C.

Аналогичным образом, вы можете использовать Decimal с NumberFormatter путем нажатия на NSDecimalNumber, так же, как вы выбрали бы Int или Double в NSNumber, чтобы использовать их с NumberFormatter.

Ответ 2

Используйте этот код:

let formatter = NumberFormatter()
formatter.numberStyle = .decimal
let string = formatter.string(from: NSNumber(integerLiteral: 3))