LoginSignup
32
31

More than 5 years have passed since last update.

[Swift] バリデーションチェックは、正規表現で!

Posted at

はじめに

アプリの入力データを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にアップしていますので、合わせて御覧ください。

以上です。

32
31
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
31