Last active
July 8, 2016 10:32
-
-
Save rjchatfield/2b274f3075065f1e16bb to your computer and use it in GitHub Desktop.
Validating PhoneNumber type in Swift with a failable initialiser and an enum (for type safety)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
typealias RegexPattern = String | |
let aussiePhoneNumber = 0424_555_123 | |
let brokePhoneNumber = 0424_555_1231 | |
enum PhoneNumberType: RegexPattern { | |
// List all regex patterns | |
case AussieMobile = "(?:\\+?61|0)4(?:[01]\\d{3}|(?:2[1-9]|3[0-57-9]|4[7-9]|5[0-15-9]|6[679]|7[3-8]|8[1478]|9[07-9])\\d{2}|(?:20[2-9]|444|52[0-6]|68[3-9]|70[0-7]|79[01]|820|890|91[0-4])\\d|(?:200[0-3]|201[01]|8984))\\d{4}$" | |
// case ... | |
// case ... | |
// Helper | |
var regexVal: RegexPattern { return self.rawValue } | |
} | |
private extension Int { | |
func isA(type: PhoneNumberType) -> Bool { | |
let matches = self.numberOfMatches(regex: type.regexVal) | |
return matches > 0 | |
} | |
func numberOfMatches(regex regexPattern: RegexPattern, options: NSRegularExpressionOptions = [], minimumIntegerDigits: Int = 20) -> Int? { | |
let formatter = NSNumberFormatter() | |
formatter.minimumIntegerDigits = minimumIntegerDigits | |
guard let | |
nStr = formatter.stringFromNumber(self), // Create a n-character string with leading zeros | |
regex = try? NSRegularExpression(pattern: regexPattern, options: options) | |
else { return nil } | |
let len = nStr.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) | |
return regex.numberOfMatchesInString(nStr, options: [], range: NSMakeRange(0, len)) | |
} | |
} | |
struct PhoneNumber { | |
let number: Int | |
init?(_ number: Int, phoneNumberType: PhoneNumberType) { | |
guard number.isA(phoneNumberType) else { return nil } | |
self.number = number | |
} | |
} | |
PhoneNumber(aussiePhoneNumber, phoneNumberType: .AussieMobile) // Optional<PhoneNumber>(PhoneNumber(0424_555_123)) | |
PhoneNumber(brokePhoneNumber, phoneNumberType: .AussieMobile) // nil |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment