役に立つかどうかよくわからないTipsシリーズ
また今回も文字列の拡張に関することです
例えばテキストフィールドなどで入力された文字などに
入力値チェックをすることも多いかと思います
そこには「アルファベットしか入れられないよ」とか「数字だけだよー」とか
そういう仕様はよくあるんじゃないかと思います
それを実現する方法としては
例えば正規表現でチェックするという手段もありますし
他にも色々とありそうです
その中から今回は「キャラクターセット」で判定を行う方法で
String
の拡張をしてみますね
ベースメソッドを用意する
挙動を実現するためのベースとなるメソッドです
3行だけでシンプルに書けました
extension String {
public func isOnly(structuredBy chars: String) -> Bool {
let characterSet = NSMutableCharacterSet()
characterSet.addCharactersInString(chars)
return self.stringByTrimmingCharactersInSet(characterSet).length <= 0
}
}
このメソッドは
渡したchars
に書かれている文字列のみで自身が構成されているか
を返すメソッドです
例えば
"ABC".isOnly(structuredBy: "ABCDEF") // true
"ABC".isOnly(structuredBy: "BCDEFG") // false
"ABC".isOnly(structuredBy: "abcdef") // false
最初の1行目は
文字列"ABC"
は、"A"
、"B"
、"C"
、"D"
、"E"
、"F"
のいずれかのみで構成されているか?
ということですのでtrue
を返します
2行目は
"BCDEFG"
の中に"A"
がないのでfalse
3行目は
大文字と小文字はちゃんと区別しますよーということです
ラッピングプロパティを作る
ベースメソッドだけ用意すれば、なんなりとできるのですが
よく使うパターンをラッピングプロパティとして用意しておけば便利です
これはアプリの仕様に合わせ、必要に応じて追加・削除をしてもらえばと思いますが
普段から使えるものとして以下を用意しました
extension String {
/// 半角数字のみで構成されているかどうか
public var isOnlyNumber: Bool {
return self.isOnly(structuredBy: "0123456789")
}
/// 半角アルファベットのみで構成されているかどうか
public var isOnlyAlphabet: Bool {
return self.isOnly(structuredBy: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
}
/// 半角英数字のみで構成されているかどうか
public var isOnlyAlphabetAndNumber: Bool {
let chars = String.structureOfAlphabetAndNumber
return self.isOnly(structuredBy: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
}
}
プロパティ化しておくことで、可読性もよくなりますし、コードもすっきりします
"ABC".isOnlyNumber // false
"ABC".isOnlyAlphabetAndNumber // true
ただし、なんだかメソッド定義側が
ガチャガチャしてる気がします
もうひと手間足してみることにします
extension String {
/// 数字
public static let structureOfNumber = "0123456789"
/// 小英字
public static let structureOfLowercaseAlphabet = "abcdefghijklmnopqrstuvwxyz"
/// 大英字
public static let structureOfUppercaseAlphabet = structureOfLowercaseAlphabet.uppercaseString
/// 英字
public static let structureOfAlphabet = structureOfLowercaseAlphabet + structureOfUppercaseAlphabet
/// 英数字
public static let structureOfAlphabetAndNumber = structureOfAlphabet + structureOfNumber
/// 半角数字のみで構成されているかどうか
public var isOnlyNumber: Bool {
let chars = String.structureOfNumber
return self.isOnly(structuredBy: chars)
}
/// 半角アルファベットのみで構成されているかどうか
public var isOnlyAlphabet: Bool {
let chars = String.structureOfAlphabet
return self.isOnly(structuredBy: chars)
}
/// 半角英数字のみで構成されているかどうか
public var isOnlyAlphabetAndNumber: Bool {
let chars = String.structureOfAlphabetAndNumber
return self.isOnly(structuredBy: chars)
}
}
isOnly(structuredBy:)
メソッドに渡すchars
を
String
のクラス定数として小分けに定義しました
先ほどの3つのメソッドの中身が整理できました
"0123456789"
を3回も書くなんて非効率でしたのでね
これらを用意することにより、
拡張性も少しだけあがりました
例えば半角英数字に加えて半角スペースも許可するならこんな感じのプロパティを用意します
extension String {
public var isOnlyAlphabetAndNumberAndSpace: Bool {
let chars = String.structureOfAlphabetAndNumber + " "
return self.isOnly(structuredBy: chars)
}
}
電話番号のような数字とハイフンのみを許可するなら
extension String {
public var isOnlyNumberAndHyphen: Bool {
let chars = String.structureOfNumber + "-"
return self.isOnly(structuredBy: chars)
}
}
こんな感じでしょうか
電話番号やメールアドレスなどの形式があっているかどうかのバリデーションチェックをするなら
やはり冒頭に書いたとおり正規表現を用いるなどする必要もありますが
入力された文字がまず許可していい値かどうかを判定する用途等であれば
これだけでなかなか強力な機能となります