はじめに
アプリの入力データをif文とAnd条件で数珠つなぎで判定していくとカオスになりますよね。
やはりここは、正規表現の出番ですね。
ただし、Swiftは、正規表現が扱いづらいため、
少しだけ簡単に利用できるようにします。
Custom Operatorsを利用する
Regexp.swift
import UIKit
infix operator =~
infix operator !~
func =~(lhs: String, rhs: String) -> Bool {
guard let regex = try? NSRegularExpression(pattern: rhs,
options: NSRegularExpression.Options()) else {
return false
}
return regex.numberOfMatches(in: lhs,
options: NSRegularExpression.MatchingOptions(),
range: NSRange(location: 0, length: lhs.characters.count)) > 0
}
func !~(lhs: String, rhs: String) -> Bool {
return !(lhs=~rhs)
}
利用方法
よく使いそうなパターンをextensionに追加すると、下記のようになります。
正規表現については、ここでは触れません。
Swift+Validation.swift
import Foundation
extension String {
func isNumeric() -> Bool{
return (self =~ "(^$)|(^\\d*$)")
}
func isNumeric(length: Int) -> Bool {
return (self =~ "(^$)|(^\\d{\(length)}$)")
}
func isUrl() -> Bool {
return (self =~ "^(https?|ftp)(:\\/\\/[-_.!~*\\'()a-zA-Z0-9;\\/?:\\@&=+\\$,%#]+)$")
}
func isEmail() -> Bool {
return (self =~ "^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$")
}
func isTelNo() -> Bool {
return (self =~ "^\\d{2,4}-\\d{1,4}-\\d{4}$")
}
func isdate(format: String) -> Bool {
return (self =~ "^\\d{4}\(format)\\d{1,2}\(format)\\d{1,2}$")
}
func isTime() -> Bool {
return (self =~ "^\\d{1,2}:\\d{1,2}:\\d{1,2}$")
}
}
ユニットテスト
import XCTest
@testable import ios_Validation_demo
class ios_Validation_demoTests: XCTestCase {
override func setUp() {
super.setUp()
}
override func tearDown() {
super.tearDown()
}
func testNumeric() {
XCTAssertTrue("123456".isNumeric())
XCTAssertTrue("12345".isNumeric(length: 5))
XCTAssertFalse("1234a".isNumeric())
XCTAssertFalse("12345".isNumeric(length: 4))
}
func testUrl() {
XCTAssertTrue("http://www.yahoo.co.jp".isUrl())
XCTAssertTrue("https://www.yahoo.co.jp".isUrl())
XCTAssertFalse("https//www.yahoo.co.jp".isUrl())
XCTAssertFalse("https:www.yahoo.co.jp".isUrl())
}
func testEmail() {
XCTAssertTrue("rec@st-ventures.jp".isEmail())
XCTAssertFalse("recst-ventures.jp".isEmail())
XCTAssertFalse("rec@".isEmail())
XCTAssertFalse("@st-ventures.jp".isEmail())
}
func testTelNo() {
XCTAssertTrue("090-1234-5678".isTelNo())
XCTAssertTrue("03-1234-5678".isTelNo())
XCTAssertTrue("0120-1234-5678".isTelNo())
XCTAssertFalse("1-1234-5678".isTelNo())
XCTAssertFalse("1a-1234-5678".isTelNo())
XCTAssertFalse("03-123a-5678".isTelNo())
XCTAssertFalse("03-1234-5a78".isTelNo())
XCTAssertFalse("0312345678".isTelNo())
XCTAssertFalse("03-12345678".isTelNo())
XCTAssertFalse("031234-5678".isTelNo())
}
func testDate() {
XCTAssertTrue("2016-1-1".isdate(format:"-"))
XCTAssertTrue("2016-12-19".isdate(format:"-"))
XCTAssertTrue("2016/12/19".isdate(format:"/"))
XCTAssertFalse("2016/12/19".isdate(format:"-"))
XCTAssertFalse("20166-12-19".isdate(format:"-"))
XCTAssertFalse("2016-123-19".isdate(format:"-"))
XCTAssertFalse("2016-12-191".isdate(format:"-"))
XCTAssertFalse("201-12-19".isdate(format:"-"))
XCTAssertFalse("201612-19".isdate(format:"-"))
XCTAssertFalse("2016-1219".isdate(format:"-"))
XCTAssertFalse("201a-12-19".isdate(format:"-"))
XCTAssertFalse("2016-1a-19".isdate(format:"-"))
XCTAssertFalse("2016-12-1a".isdate(format:"-"))
}
func testTime() {
XCTAssertTrue("20:10:10".isTime())
XCTAssertTrue("1:1:1".isTime())
XCTAssertFalse("10-10-10".isTime())
XCTAssertFalse("123:10:10".isTime())
XCTAssertFalse("12:123:10".isTime())
XCTAssertFalse("12:12:123".isTime())
XCTAssertFalse("1010:10".isTime())
XCTAssertFalse("10:1010".isTime())
XCTAssertFalse("1a:10:10".isTime())
XCTAssertFalse("10:a0:10".isTime())
XCTAssertFalse("10:10:1a".isTime())
}
}
まとめ
如何でしたか?
ちょっとだけ楽になりましたね。
本件について、Githubにアップしていますので、合わせて御覧ください。
以上です。