web-dev-qa-db-fra.com

Swift 3 Decimal, NSDecimal et NSDecimalNumber

J'essaie d'utiliser NumberFormatter avec Swift 3 Decimal, mais je ne sais pas comment Decimal est réellement mis en œuvre. Le problème que je rencontre est que Decimal est une structure, donc je dois le relier à un NSDecimalNumber chaque fois que je veux utiliser un formateur, ce que j'aimerais éviter.

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

Est-ce la solution de contournement idéale pour implémenter ma propre extension qui prend un Decimal?

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

Plus généralement, chaque fois que je devrai saisir un type d'objet, vais-je avoir besoin de ponter Decimal ou d'écrire plus d'extensions?

MODIFIER

Je suppose que je me pose des questions plus générales sur NSDecimalDecimal et NSDecimalNumber in Swift 3. Je ne sais pas du tout ce qui se passe Dois-je remplacer NSDecimalNumber par Decimal pour Swift 3? Les documents écrivent:

La superposition Swift du framework Foundation fournit la structure Decimal, qui relie la classe NSDecimalNumber. Le type de valeur Decimal offre les mêmes fonctionnalités que le type de référence NSDecimalNumber, et les deux peuvent être utilisés de manière interchangeable dans Swift code qui interagit avec les API Objective-C. Ce comportement est similaire à la façon dont Swift relie les types de chaîne, de chiffres et de collection standard à leurs classes Foundation correspondantes.

Au début, je pensais que Decimal était le nouveau NSDecimalNumber comme Error est le nouveau NSError - mais maintenant je n'en suis pas si sûr. Cela dit également que "le type de valeur décimale offre les mêmes fonctionnalités que le type de référence NSDecimalNumber" - est-ce vraiment vrai? Je n'arrive pas à obtenir la plupart des mêmes fonctionnalités (sans les combler d'abord, bien sûr, c'est ce qu'elles signifient?). J'ai trouvé quelques posts et quelques infos ici et là, mais rien de si convaincant. Quelqu'un a-t-il des connaissances ou des idées?

Mon application utilise spécifiquement NSDecimalNumber pour la devise et le formatage, donc l'arrondi et le formatage sont une priorité élevée.

29
Alex

J'ai posé ma question sur le forum des utilisateurs de Swift et j'ai obtenu une réponse merveilleuse, consultez-la ici: https://lists.Swift.org/pipermail/Swift-users/Week-of-Mon-20161219/004220 .html

Version texte de la réponse:

Swift 3 a introduit la classe Decimal, qui, au début, je pensais était censée "remplacer" NSDecimalNumber dans Swift, comme Error est le nouveau NSError, etc. Cependant, après une enquête plus approfondie, il n'est pas clair de moi que c'est effectivement le cas. Il semble que Swift 3 Decimal est plus juste un NSDecimal, mais avec un pontage afin qu'il puisse utiliser les méthodes de NSDecimalNumber en cas de besoin. Ce que je me demande, est-ce que je devrais remplacer NSDecimalNumber dans mon application avec Decimal? Decimal est-il le successeur de NSDecimalNumber dans Swift?

Decimal est en fait une structure, pas une classe, et en fait c'est juste le Swift pour la structure NSDecimal dans Objective-C. Dans Swift, les fonctions comme NSDecimalAdd sont exposés en tant qu'opérateurs sur Decimal et sont utilisés pour satisfaire aux exigences de divers protocoles numériques comme SignedNumber.

Le résultat final est que Decimal ressemble beaucoup à Int ou Double— c'est un type de valeur qui peut être facilement utilisé pour faire toutes sortes de calculs. NSDecimalNumber, alors, est équivalent à NSNumber.

Puisque mon application fait beaucoup de mise en forme, elle nécessiterait beaucoup de cast entre Decimal et NSDecimalNumber, ou l'ajout d'extensions à utiliser, donc je ne pense pas que ce serait naturel/pratique sans beaucoup extensions. Swift prévoit-il d'améliorer Decimal pour être plus utilisable avec NumberFormatter ou d'autres API numériques orientées objet? J'espère avoir fourni suffisamment d'informations pour répondre à ma question.

Les API Objective-C qui utilisent NSDecimalNumber doivent être pontées vers Decimal, tout comme NSString est pontée vers String. Ce pontage peut ne pas fonctionner pour les méthodes de catégorie, cependant; vous pouvez les exposer à Swift en écrivant une extension sur Decimal qui convertit self en NSDecimalNumber puis appelle à votre Objective-C méthodes.

De même, vous devriez pouvoir utiliser Decimal avec NumberFormatter en transtypant en NSDecimalNumber, comme vous le feriez pour Int ou Double vers NSNumber pour les utiliser avec NumberFormatter.

27
Alex