[iOS 10] NSMeasurementを使って簡単に単位を変換する

2016.09.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは!モバイルアプリサービス部の加藤 潤です。
今回はiOS 10で追加された NSMeasurement やその周辺クラス群について取り上げたいと思います。

これからご紹介するNSMeasurementなどはObjective-Cの世界ではclassですが、Swiftの世界ではstructureです。説明文ではクラスとして表現(頭にNSが付く)しますが、ソースコード部分はSwiftなので頭にNSは付きません。機能としては同じものを指しています。

iOS 10で追加されたクラス群

NSMeasurement

  • 値を異なる単位に変換したり、2つの値の合計や差分を計算する機能を提供する。
  • NSMeasurementFormatterを使うことでローカライズした値と単位をユーザーに表示することが可能。
  • NSUnitdouble値で構成される。

NSUnit

  • 単位を表す。
  • NSUnit自体は抽象クラスであり、実際にはサブクラスを使用する。
  • NSUnitのサブクラスはMeasurementFormatterを使ったNSMeasurementの文字列表現の生成に使用されるsymbolを持つ。

NSDimension

  • 次元を持つ単位を表す。
  • NSUnitのサブクラス。
  • NSDimension自体は抽象クラスであり、実際にはサブクラスを使用する。
  • 同じ種類の異なる単位に変換する機能を提供する。
  • Foundationフレームワークが一般的な物理量(質量、長さ、期間、速度など)を表す様々なサブクラスを提供してくれている。
    • 次元を持つ単位を扱う場合はFoundationフレームワークのサブクラスを使用するか、もしくはNSDimensionのサブクラスを自作する。
    • 次元を持たない単位(count, score, ratioなど)を表す場合はNSUnitのサブクラスを自作する。

Foundationフレームワークが提供するNSDimensionのサブクラス(一部)

  • 以下はFoundationフレームワークが提供するNSDimensionのサブクラスの一部です。 他にもたくさんありますので、詳細はAPI Referenceをご覧ください。
    • NSUnitAngle(角度)
    • NSUnitDuration(期間)
    • NSUnitMass(質量)
    • NSUnitSpeed(速度)

NSMeasurementFormatter

  • NSUnitNSMeasurementを適切にフォーマット、ローカライズする機能を提供する。

NSMeasurementを使って単位を変換する

  • 時間を秒に変換してみます。
// 「24時間」を定義
var hours = Measurement(value: 24, unit: UnitDuration.hours)
print(hours)   // 24.0 hr

// 「24時間」を「秒」に変換(non-mutating)
let seconds = hours.converted(to: UnitDuration.seconds)
print(seconds) // 86400.0 s

// 「24時間」を「秒」に変換(mutating)
hours.convert(to: UnitDuration.seconds)
print(hours)   // 86400.0 s

NSMeasurementFormatterを使ってNSMeasurementをフォーマット、ローカライズする

  • NSMeasurementFormatterを使ってNSMeasurementをフォーマット、日本語にローカライズしてみます。
// 「24時間」を定義
var hours = Measurement(value: 24, unit: UnitDuration.hours)

print(NSLocale.current) // en_US

// ロケール設定なし(current localeが使われる)
// unitStyle設定なし(NSFormattingUnitStyleMediumが使われる)
let measurementFormatter = MeasurementFormatter()

let string1 = measurementFormatter.string(from: hours)
print(string1) // 24 hr

// unitStyleをlongに設定
measurementFormatter.unitStyle = .long
let string2 = measurementFormatter.string(from: hours)
print(string2) // 24 hours

// unitStyleをshortに設定
measurementFormatter.unitStyle = .short
let string3 = measurementFormatter.string(from: hours)
print(string3) // 24h

// ロケール設定あり(ja_JP)
measurementFormatter.locale = Locale(identifier: "ja_JP")
let string4 = measurementFormatter.string(from: hours)
print(string4) // 24時間

おわりに

NSMeasurementとその関連クラス群の登場によって、単位の変換や計算が楽になりました。特に単位の変換ロジックを開発者が意識しなくて良くなったのは地味に嬉しいです。

参考