(追記)
@mono0926 さんからコメント頂きまして、String
の関数であるapplyingTransform(_:reverse)
を使うと同様のことができるようです!
iOSなら9+で使えるので、CFString系を扱わずに済むかと思います。
以下コメント原文ママ
"アケマシテオメデトウゴザイマス".applyingTransform(.fullwidthToHalfwidth, reverse: false)
"アケマシテオメデトウゴザイマス".applyingTransform(.fullwidthToHalfwidth, reverse: true)
※以下の内容はSwift2時点のものです。
文章中の"数字"や、ユーザーの入力した文字列中の "数字"で、もし 全角だったら半角に変換をしたかったので、
まとめてみました。
実装
全角→半角になるものとしては、
- 全角数字(0, 1, ..., 9)
- 全角英数字(A, B, C, ...)
- 全角カタカナ (ア, イ, ウ, エ, オ, ...)
- その他全角/半角で記号が用意されているもの(ハイフンとか)
があるので、正規表現だけだとちょっと大変です。
そこで、 CoreFoundationで提供されている、 CFStringTransform()
を使います。
public func CFStringTransform(string: CFMutableString!, _ range: UnsafeMutablePointer<CFRange>, _ transform: CFString!, _ reverse: Bool) -> Bool
-
第1引数には **
CFMutableString
**を渡します。
Swiftの場合、 **String
**から直接 **CFMutableString
**に変換するのは大変なので、 **NSMutableString
**を経由してCFMutableString
に変換します。 -
第2引数には、rangeを渡しますが、文字列全てを対象にするなら nilで大丈夫です。
-
第3引数には、変換をかけるタイプを指定します。今回は全角/半角変換をしたいので、 **
kCFStringTransformFullwidthHalfwidth
**を指定します。 -
第4引数には、かける変換を逆変換にするかどうかを指定します。今回の場合、 **
kCFStringTransformFullwidthHalfwidth
**を指定するので、- falseを渡せばタイプの名前通り、全角から半角に変換します
- trueを渡せば逆、つまり半角から全角に変換します。
これをふまえて、以下のように実装をします。
extension String {
private func convertFullWidthToHalfWidth(reverse: Bool) -> String {
let str = NSMutableString(string: self) as CFMutableString
CFStringTransform(str, nil, kCFStringTransformFullwidthHalfwidth, reverse)
return str as String
}
var hankaku: String {
return convertFullWidthToHalfWidth(reverse: false)
}
var zenkaku: String {
return convertFullWidthToHalfWidth(reverse: true)
}
}
変換してみる
使用例と変換結果は以下のようになります。
print("000".hankaku) // 000
print("000".zenkaku) // 000
print("アアア".hankaku) // アアア
print("AAA".hankaku) // AAA
print("AAA".zenkaku) // AAA
print("あああ".hankaku) // あああ (そのまま)
print("000".hankaku) // 000 (半角のものはそのまま)
数字だけ半角/全角変換をしたい
上記のままだと、たとえば、
000 : あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。
という文章に対して、数字だけ半角にしたいと思い半角への変換を実行すると...
let text = "000 : あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。"
print(text.hankaku)
// -> 000 : あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。
と、数字以外のカタカナ、濁点等も半角になってしまいます。 数字だけ変換したい場合は、正規表現で文章中から半角或いは全角数字を抽出して、全角/半角の変換を行う必要があります。
なので、以下のように追記してみます。
extension String {
// 前略
private func convertFullWidthToHalfWidthOnlyNumber(fullWidth: Bool) -> String {
var str = self
let pattern = fullWidth ? "[0-9]+" : "[0-9]+"
let regex = try! NSRegularExpression(pattern: pattern, options: [])
let results = regex.matchesInString(str, options: [], range: NSMakeRange(0, str.characters.count))
results.reverse().forEach {
let subStr = (str as NSString).substringWithRange($0.range)
str = str.stringByReplacingOccurrencesOfString(
subStr,
withString: (fullWidth ? subStr.zenkaku : subStr.hankaku))
}
return str
}
var hankakuOnlyNumber: String {
return convertFullWidthToHalfWidthOnlyNumber(false)
}
var zenkakuOnlyNumber: String {
return convertFullWidthToHalfWidthOnlyNumber(true)
}
}
これで、 **hankakuOnlyNumber
**と **zenkakuOnlyNumber
**が使えるようになるので、
let text = "000 : あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。"
print(text.hankakuOnlyNumber)
// -> 000 : あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。。
無事、文章中の数字だけ半角に出来ました。
逆に **zenkakuOnlyNumber
**を使えば、
let text2 = "000 : あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。"
print(text2.zenkakuOnlyNumber)
// -> 000 : あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。
と、数字だけ全角にできます。
コード全文
こちらにおいておきます。
おまけ
他にも、ひらがな/カタカナ変換なども用意されているので、同じようにやってみれば、与えた文字列に対して変換をかけられます。
計算型プロパティの名前悩んだのですが、英語でfullWidth
とかにするよりはzenkaku
のがわかりやすいかなと思ったのでそうしましたが、気に入らなければ英語に直してください〜。