Xcode
iOS
アプリ
extension
Swift

[Swift]iOSのデフォルトの関数を活用した Validation String Extension集

More than 1 year has passed since last update.

前置き

個人的に業務や自作でアプリを作るたびに、何回も同じようなことを調べてExtension を作成しているので、メモ書き程度に残しておきたかった。

String Extension Variables

【前後空白改行】

extension String {

    var hasSpaceAndNewlines: Bool {
        return self.isEmpty || self.trimmingCharacters(in: .whitespacesAndNewlines) != self
    }

}

print("text".hasSpaceAndNewlines) // false 任意の文字
print("".hasSpaceAndNewlines)     // true 空
print(" ".hasSpaceAndNewlines)    // true 半角スペース
print(" ".hasSpaceAndNewlines)    // true 全角スペース
print("\n".hasSpaceAndNewlines)  // true 改行
print("\n\n".hasSpaceAndNewlines)// true 改行2回

.whitespacesAndNewlines以外にもオプションが存在する。

【地域・言語】

extension String {

    /// 言語設定が「英語」かどうか ※1
    var isEnglish: Bool {
        return self.hasPrefix("en")
    }

    /// 言語設定が「日本語」かどうか
    var isJapanese: Bool {
        return self.hasPrefix("ja")
    }

    /// 地域設定が「日本語」かどうか ※2
    var isJapan: Bool {
        return self.hasSuffix("JP")
    }

}

/// ※1
print("ja".isJapanese)     // true
print("ja-EN".isJapanese)  // true
print("en-JP".isJapanese)  // false
print("aja-EN".isJapanese) // false

/// ※2
print("ja".isJapan)     // false
print("ja-EN".isJapan)  // false
print("en-JP".isJapan)  // true
print("aja-EN".isJapan) // false

Locale.preferredLanguagesで端末の表示言語を取得できるので、そちらを使っても良かったが、サーバーからくる言語判定をしたかったので、少し広めに使い勝手良くしました。
上記以外の言語・地域はお好みでExtensionに追加してくだしい。

【日本語判定】

extension String {

    /// 「漢字」かどうか
    var isKanji: Bool {
        let range = "^[\u{3005}\u{3007}\u{303b}\u{3400}-\u{9fff}\u{f900}-\u{faff}\u{20000}-\u{2ffff}]+$"
        return NSPredicate(format: "SELF MATCHES %@", range).evaluate(with: self)
    }

    /// 「ひらがな」かどうか
    var isHiragana: Bool {
        let range = "^[ぁ-ゞ]+$"
        return NSPredicate(format: "SELF MATCHES %@", range).evaluate(with: self)
    }

    /// 「カタカナ」かどうか
    var isKatakana: Bool {
        let range = "^[ァ-ヾ]+$"
        return NSPredicate(format: "SELF MATCHES %@", range).evaluate(with: self)
    }

}

print("otoko".isKanji)   // false
print("男".isKanji)      // true
print("男otoko".isKanji) // false

長文や「ひらがな」「カタカナ」が入り混じる場合はrangeをがっちゃんこする必要があります。

【日本語変換】

extension String {

    /// 「ひらがな」に変換 ※1
    var toHiragana: String? {
        return self.applyingTransform(.hiraganaToKatakana, reverse: false)
    }

    /// 「カタカナ」に変換
    var toKatakana: String? {
        return self.applyingTransform(.hiraganaToKatakana, reverse: true)
    }

    /// 「ひらがな」を含むかどうか ※2
    var hasHiragana: Bool {
        guard let hiragana = self.toKatakana else { return false }
        return self != hiragana // 1文字でもカタカナに変換されている場合は含まれると断定できる
    }

    /// 「カタカナ」を含むかどうか
    var hasKatakana: Bool {
        guard let katakana = self.toHiragana else { return false }
        return self != katakana // 1文字でもひらがなに変換されている場合は含まれると断定できる
    }

}

/// ※1
print("hiragana".toHiragana) // optional("hiragana") 英語はそのまま
print("ひらがな".toHiragana)   // optional("ひらがな") ひらがなはそのまま
print("ヒラガナ".toHiragana)   // optional("ひらがな") 変換された

/// ※2
print("hiragana".hasHiragana)             // false
print("ひらがな".hasHiragana)               // true
print("ヒラガナ".hasHiragana)               // false
print("hiraganaひらがなヒラガナ".hasHiragana) // true

applyingTransformでサクッと作れる。.hiraganaToKatakana以外にもオプションがあります。
単語や分に含まれるかどうかは、先ほどのNSPredicateを使ったバリデーションでも含まれるかの判定を作れるが、長くなってしまうのでこちらで作る方が短くて完結かと。

【英語大文字小文字】

extension String {

    /// 「小文字だけ」かどうか
    var isLowrcased: Bool {
        return self == self.lowercased()
    }

    /// 「大文字だけ」かどうか
    var isUppercased: Bool {
        return self == self.uppercased()
    }

}

print("english".isLowrcased) // true
print("English".isLowrcased) // false
print("ひらがな".isLowrcased) // true ひらがなは変換されないのでtrueとなる

英語にしか使えないので、ちゃんと使いたい方はNSPredicateでバリデーションしてくだしい。

【URL】

extension String {

   var isUrl: Bool {
       let linkValidation = NSTextCheckingResult.CheckingType.link.rawValue
       guard let detector = try? NSDataDetector(types: linkValidation) else { return false }

       let results = detector.matches(in: self, options: .reportCompletion, range: NSMakeRange(0, self.characters.count))
       return results.first?.url != nil
    }

}

print("http".isUrl)      // false
print("https".isUrl)     // false
print("http://".isUrl)   // false
print("https://".isUrl)  // false
print("http://a".isUrl)  // true
print("https://a".isUrl) // true

デフォルトで画像の拡張子あたりまでバリデーションしてくれたら、なおよかったんですけど笑
参考に載せましたが、 NSTextCheckingResultPhoneNumber,Addressとかもあります。

全部まとめたやつ

extension String {

    /// 前後にスペース、改行があるかどうか
    var hasSpaceAndNewlines: Bool {
        return self.isEmpty || self.trimmingCharacters(in: .whitespacesAndNewlines).characters.isEmpty
    }

    /// 言語設定が「英語」かどうか
    var isEnglish: Bool {
        return self.hasPrefix("en")
    }

    /// 言語設定が「日本語」かどうか
    var isJapanese: Bool {
        return self.hasPrefix("ja")
    }

    /// 地域設定が「日本語」かどうか ※2
    var isJapan: Bool {
        return self.hasSuffix("JP")
    }

    /// 「漢字」かどうか
    var isKanji: Bool {
        let range = "^[\u{3005}\u{3007}\u{303b}\u{3400}-\u{9fff}\u{f900}-\u{faff}\u{20000}-\u{2ffff}]+$"
        return NSPredicate(format: "SELF MATCHES %@", range).evaluate(with: self)
    }

    /// 「ひらがな」かどうか
    var isHiragana: Bool {
        let range = "^[ぁ-ゞ]+$"
        return NSPredicate(format: "SELF MATCHES %@", range).evaluate(with: self)
    }

    /// 「カタカナ」かどうか
    var isKatakana: Bool {
        let range = "^[ァ-ヾ]+$"
        return NSPredicate(format: "SELF MATCHES %@", range).evaluate(with: self)
    }

    /// 「ひらがな」に変換 ※1
    var toHiragana: String? {
        return self.applyingTransform(.hiraganaToKatakana, reverse: false)
    }

    /// 「カタカナ」に変換
    var toKatakana: String? {
        return self.applyingTransform(.hiraganaToKatakana, reverse: true)
    }

    /// 「ひらがな」を含むかどうか ※2
    var hasHiragana: Bool {
        guard let hiragana = self.toKatakana else { return false }
        return self != hiragana // 1文字でもカタカナに変換されている場合は含まれると断定できる
    }

    /// 「カタカナ」を含むかどうか
    var hasKatakana: Bool {
        guard let katakana = self.toHiragana else { return false }
        return self != katakana // 1文字でもひらがなに変換されている場合は含まれると断定できる
    }

    /// 「小文字だけ」かどうか
    var isLowrcased: Bool {
        return self == self.lowercased()
    }

    /// 「大文字だけ」かどうか
    var isUppercased: Bool {
        return self == self.uppercased()
    }

    /// URLかどうか
    var isUrl: Bool {
        let linkValidation = NSTextCheckingResult.CheckingType.link.rawValue
        guard let detector = try? NSDataDetector(types: linkValidation) else { return false }

        let results = detector.matches(in: self, options: .reportCompletion, range: NSMakeRange(0, self.characters.count))
        return results.first?.url != nil
    }

}

あとがき

わりとピンポイントな使い所のものしかないので、「あ、これ!」みたいなやつはなかったかと思います。笑

今回は自分のプロジェクトの使い勝手が良いように作成しているので、上記はあくまでも指標程度に考えていただき、みなさんの使い勝手が良いように書き換えてくだされば、と思っております。

参考

言語・地域

ひらがな・カタカナ

URL

その他

Phone and Address Validations
1. Check if exists phone number in String
2. Extracting address elements from a String using NSDataDetector in Swift 3.0
3. 正则表达式基础