Xcode
iOS
Swift

[Swift] 文字の種類ごとに全角/半角に変換する

More than 1 year has passed since last update.

とある案件で,入力された文字のうち,数字は半角,カタカナは全角に変換してほしい,というものがありました.

どうせなら,ということで,数字,英字,カタカナ,その他(記号)ごとに全角/半角を指定できるようなString型のExtensionを作りましたので,共有したいと思います.

ぱっと作ったので,もっといい方法があるかもしれません.
もっと簡単にできる方法がありましたら,コメントの方でご教授お願いしますm(._.)m

関連部分コード

細かい説明は省きます.

enum CharacterType {
    case Numeric, English, Katakana, Other
}

func transformFullwidthHalfwidth(transformTypes types :[CharacterType], reverse :Bool=false) -> String {
    var transformedChars :[String] = []

    let chars = self.characters.map{ String($0) }
    chars.forEach{
        let halfwidthChar = NSMutableString(string: $0) as CFMutableString
        CFStringTransform(halfwidthChar, nil, kCFStringTransformFullwidthHalfwidth, false)
        let char = halfwidthChar as String

        if char.isNumber(transformHalfwidth: true) {
            if let _ = types.filter({$0 == .Numeric}).first {
                CFStringTransform(halfwidthChar, nil, kCFStringTransformFullwidthHalfwidth, reverse)
                transformedChars.append(halfwidthChar as String)
            } else {
                transformedChars.append($0)
            }
        }
        else if char.isEnglish(transformHalfwidth: true) {
            if let _ = types.filter({$0 == .English}).first {
                CFStringTransform(halfwidthChar, nil, kCFStringTransformFullwidthHalfwidth, reverse)
                transformedChars.append(halfwidthChar as String)
            } else {
                transformedChars.append($0)
            }
        }
        else if char.isKatakana() {
            if let _ = types.filter({$0 == .Katakana}).first {
                CFStringTransform(halfwidthChar, nil, kCFStringTransformFullwidthHalfwidth, reverse)
                transformedChars.append(halfwidthChar as String)
            } else {
                transformedChars.append($0)
            }
        }
        else {
            if let _ = types.filter({$0 == .Other}).first {
                CFStringTransform(halfwidthChar, nil, kCFStringTransformFullwidthHalfwidth, reverse)
                transformedChars.append(halfwidthChar as String)
            } else {
                transformedChars.append($0)
            }
        }
    }

    var transformedString = ""
    transformedChars.forEach{ transformedString += $0 }

    return transformedString
}

func isNumber(transformHalfwidth transform :Bool) -> Bool {
    let halfwidthStr = NSMutableString(string: self) as CFMutableString
    CFStringTransform(halfwidthStr, nil, kCFStringTransformFullwidthHalfwidth, false)
    let str = halfwidthStr as String

    return Int(str) != nil ? true : false
}

func isEnglish(transformHalfwidth transform :Bool) -> Bool {
    let halfwidthStr = NSMutableString(string: self) as CFMutableString
    if transform {
        CFStringTransform(halfwidthStr, nil, kCFStringTransformFullwidthHalfwidth, false)
    }
    let str = halfwidthStr as String

    let pattern = "[A-z]*"
    do {
        let regex = try NSRegularExpression(pattern: pattern, options: .CaseInsensitive)
        let result = regex.stringByReplacingMatchesInString(str, options: [], range: NSMakeRange(0, str.characters.count), withTemplate: "")
        if result == "" { return true }
        else { return false }
    }
    catch { return false }
}

func isKatakana() -> Bool {
    let halfwidthStr = NSMutableString(string: self) as CFMutableString
    CFStringTransform(halfwidthStr, nil, kCFStringTransformFullwidthHalfwidth, true)
    let str = halfwidthStr as String

    let pattern = "^[\\u30A0-\\u30FF]+$"
    do {           
        let regex = try NSRegularExpression(pattern: pattern, options: .CaseInsensitive)
        let result = regex.stringByReplacingMatchesInString(str, options: [], range: NSMakeRange(0, str.characters.count), withTemplate: "")
        if result == "" { return true }
        else { return false }
    }
    catch { return false }
}

実行結果

let str = "aAこンニチハ123456-+ー=+"
print("そのまま            :", str)
print("カタカナ            :", str.transformFullwidthHalfwidth(transformTypes: [.Katakana]))
print("数字               :", str.transformFullwidthHalfwidth(transformTypes: [.Numeric]))
print("英字               :", str.transformFullwidthHalfwidth(transformTypes: [.English]))
print("その他             :", str.transformFullwidthHalfwidth(transformTypes: [.Other]))
print("英数字             :", str.transformFullwidthHalfwidth(transformTypes: [.Numeric, .English]))
print("カタカナ(全角)       :", str.transformFullwidthHalfwidth(transformTypes: [.Katakana], reverse: true))
print(
    "数字半角,カタカナ全角 :",
    str.transformFullwidthHalfwidth(transformTypes: [.Numeric])
        .transformFullwidthHalfwidth(transformTypes: [.Katakana], reverse: true)
)

// 出力 ----------
//そのまま            : aAこンニチハ123456-+ー=+
//カタカナ            : aAこンニチハ123456-+ー=+
//数字               : aAこンニチハ123456-+ー=+
//英字               : aAこンニチハ123456-+ー=+
//その他             : aAこンニチハ123456-+ー=+
//英数字             : aAこンニチハ123456-+ー=+
//カタカナ(全角)       : aAこンニチハ123456-+ー=+
//数字半角,カタカナ全角 : aAこンニチハ123456-+ー=+