FoundationのNumberFormatterを試す

nextpublishing.jp

上記を読んでいる時にNumberFormatterが出てきた。
使ったことがなかったので試す。


開発環境

> swift --version
swift-driver version: 1.26.9 Apple Swift version 5.5.1 (swiftlang-1300.0.31.4 clang-1300.0.29.6)
Target: x86_64-apple-macosx11.0

> xcodebuild -version
Xcode 13.1
Build version 13A1030d

NumberFormatterとは

A formatter that converts between numeric values and their textual representations.
https://developer.apple.com/documentation/foundation/numberformatter

数値と文字列間で変換するクラス。

Instances of NumberFormatter format the textual representation of cells that contain NSNumber objects and convert textual representations of numeric values into NSNumber objects.
https://developer.apple.com/documentation/foundation/numberformatter

取り扱う数値の型はNSNumber

NumberFormatterを使わずに変換

簡単な場合は以下で事足りる。

// Int -> String
let number = 1234567
let numberString = number.description
print(type(of: numberString))  // String

// String -> Int
let numberString = "1234567"
let number = Int(numberString)
print(type(of: number))  // Optional<Int>

どういう時にNumberFormatterを使うと便利なのか見ていく。

NumberFormatterで文字列→数値変換

基本形

import Foundation

let formatter = NumberFormatter()

let message = "1234567"
let number = formatter.number(from: message)
print(number?.intValue)  // Optional(1234567)

入力として許可する最大値を指定

import Foundation

let formatter = NumberFormatter()
formatter.maximum = 100

let message = "1234567"
let number = formatter.number(from: message)
print(number?.intValue)  // nil ... maximumより大きい値は受け付けない

文字列→小数

import Foundation

let formatter = NumberFormatter()

let message = "1234567.89123"
let number = formatter.number(from: message)
print(number?.doubleValue)  // Optional(1234567.89123)
print(number?.floatValue)  // Optional(1234567.9)

Doubleは期待通りの値になったが、Floatは小数点第二位以下が丸められてしまった。
(原因不明。Doubleの方が精度が良いのは前提としてあるが分からず)

NumberFormatterで数値→文字列変換

基本形

import Foundation

let formatter = NumberFormatter()

let number = 1234567
let message = formatter.string(from: NSNumber(value: number))
print(message)  // Optional("1234567")

小数→文字列

import Foundation

let formatter = NumberFormatter()
formatter.maximumFractionDigits = 10

let number = 1234567.89123
let message = formatter.string(from: NSNumber(value: number))
print(message)  // Optional("1234567.89123")

maximumFractionDigitsを指定することで小数点以下の桁数を指定できる。デフォルトは0。

import Foundation

let formatter = NumberFormatter()

let number = 1234567.8
let message = formatter.string(from: NSNumber(value: number))
print(message)  // Optional("1234568")

小数点以下の桁があふれる場合は四捨五入される模様。

locale

import Foundation

let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.locale = Locale(identifier: "ja_JP")

let number = 1234567.8
let message = formatter.string(from: NSNumber(value: number))
print(message)  // Optional("1,234,567.8")

localの指定により、ISO地域や言語コード毎に多くのフォーマッター属性のデフォルト値を決定する。

感想

以下の場合にNumberFormatterを使うと効率が良くなりそう。

  • 数値文字列変換時に小数の桁数をいじりたいとき
  • localeの適用をしたいとき

参考