kitoko552.memo

kitoko552のメモ

SwiftでStringからIntやCGFloatに変換するときの話

要点

  • Stringから数値に変換する際はNSNumberFormatter().numberFromString(string)がおすすめ
  • Intにはイニシャライザを使って変換する方法もあるが、CGFloatにはStringを引数に取るイニシャライザがない
let intStr = "3"
let intNum = NSNumberFormatter().numberFromString(intStr)
print(intNum as! Int) // 3

print(Int(intStr)) // Optional(3)
print(CGFloat(floadStr)) // コンパイルエラー

SwiftのStringにはtoInt的なメソッドはない

ごく稀に、StringをIntやCGFloatなどの数値に変換したいときがあります。
感覚的にStringのメソッドでtoInt的なものを探しますが、そういったメソッドはSwiftには存在しません。

let str: String = ... // 数字が入ったString
str. // Xcodeの補完で探そうとするもそれらしいメソッドは見当たらない。

Intならinit(string:)が使える

しかし、Intのイニシャライザにinit(string:)があります。
これを使えば引数の中身が整数の場合のみ、Optionalではありますが変換可能です。

let intStr = "3"
print(Int(intStr)) // Optional(3)

しかし、引数が小数の場合はnilが返ってくるので注意が必要です。
小数なら小数点以下は切り捨ててくれよと思いますが、このイニシャライザは残念ながらnilを返します。
そのため、引数に渡すStringの値が必ず整数であるという確信がある場合にのみ使うべきです。

let floadStr = "12.4"
print(Int(floadStr)) // nil

逆に、小数の場合はnilの方が嬉しい場合もあるので、そういったときはこれを使うのがベストな方法と言えるかもしれません。

CGFloatにはinit(string:)はない

iOSプログラミングをしているとIntと同じくらい、もしくはそれ以上によく使う数値がCGFloatです。
したがって、StringからCGFloatに変換したいときもIntのそれと同じくらいあります。
しかし、Intのときのようにはうまくいきません。
CGFloatにはinit(string:)というイニシャライザはないのです。

let floadStr = "12.4"
print(CGFloat(floadStr)) // コンパイルエラー

Intと同じようにイニシャライザを使ってなんとか変換できないかと考えて、なんとか捻り出せる解決策として、一度Dobuleに変換してからCGFloatに変換するというものがあります。
DoubleにはIntと同じようにStringを引数に取るイニシャライザがあります。
そしてCGFloatにはDoubleを引数に取るイニシャライザがあります。
これを使えばなんとかCGFloatに変換することはできます。

let floadStr = "12.4"
print(CGFloat(Double(floadStr)!)) // Optional(12.4)

しかし、この方法には問題点があります。
DoubleのイニシャライザがOptionalを返すのでunwrapする必要があるということです。
引数に渡す値が確実にDoubleに変換可能なことが分かっていれば、上のように!を使ってforced unwrapできます。
しかし、そうでなければDoubleに変換後の値がnilでないかどうかを一度チェックしてからCGFloatに変換しなければならないのでちょっと面倒です。

let floadStr = "12.4"
if let num = Double(floadStr) {
  print(CGFloat(num)) // Optional(12.4)
}

更にCGFloatに変換した値もOptionalで返ってくるので、その値を他で使いたい場合はまたunwrapしなければならず、これまた面倒です。

NSNumberFormatter().numberFromString(string:)を使う

こういった理由もあり、Stringから数値に変換する方法として、僕はNSNumberFormatter().numberFromString(string:)をお勧めします。
こいつは一度引数で渡された値をNSNumberに変換してくれます。
NSNumberに変換できれば、あとはIntでもCGFloatでもhennkannhaasで済むので万能です。
また、NSNumberからasを使って変換すると、小数をIntに変換する際はnilではなく小数切り捨ての値が返されるため、nilになると困るときには便利です。

let floadStr = "12.4"
let floatNum = NSNumberFormatter().numberFromString(floadStr) // 12.4
print(floatNum as! Int) // 12
print(floatNum as! CGFloat) // 12.4

let intStr = "3"
let intNum = NSNumberFormatter().numberFromString(intStr) // 3
print(intNum as! Int) // 3
print(intNum as! CGFloat) // 3.0

もちろん、NSNumberFormatter().numberFromString(string:)で返ってきた値がnilである可能性がある場合は、nilチェックを入れる必要がありますが、イニシャライザを使った方法よりはスッキリしたコードになると思います。