Skip to content

Instantly share code, notes, and snippets.

@nteissler
Last active August 24, 2018 05:41
Show Gist options
  • Save nteissler/a9d2b00beddcc309445ebebf1a373b49 to your computer and use it in GitHub Desktop.
Save nteissler/a9d2b00beddcc309445ebebf1a373b49 to your computer and use it in GitHub Desktop.
Pro Pattern Matching
import UIKit
// Swift 4.2 Xcode 10
//: ## Optional Patterns
func aLegacyObjcFunction() -> String! {
return "I wasn't annotated with modern objc conventions!"
}
func myFunction() -> String {
let optionalString = aLegacyObjcFunction()
// Compiles in Swift 4.1, Error in Swift 4.2
// Value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?
// return optionalString
switch optionalString {
case let output?:
return "\(output) is a `String`."
case nil:
return "Phew, that could have been segfault."
}
}
//: ## Type Casting and Enumeration Patterns
enum Error: Swift.Error {
case badError(code: Int)
case closeShave(explanation: String)
case unknown
case fatal
}
enum OtherError: Swift.Error {
case base
}
func makeURLRequest() throws { }
func getUserDetails() {
do {
try makeURLRequest()
}
// Enumeration Case Pattern with where clause
catch Error.badError(let code) where code == 50 {
print("\(code)")
}
// Enumeration Case Pattern with associated value
catch Error.closeShave(let explanation) {
print("There's an explanation! \(explanation)")
}
// Type matching pattern
catch let error as OtherError {
print("This \(error) is a base error")
}
// Type Matching Pattern
catch is Error {
print("We don't want to know much more, it must be fatal or unkown")
}
// is Swift.Error. The compiler gives us the variable error for free here
catch {
print(error)
}
}
//: ## If, While, Guard, For-In
let stringAndInt: (String, Int?) = ("Seven", 7)
if case (_, let value?) = stringAndInt {
print("The int value of the string is \(value)")
}
guard case (_, let value?) = stringAndInt else {
print("We have no value, exiting early.")
exit(0)
}
var guess: Int = 0
while case 0...10 = guess {
// Playgrounds don't support reading from stdin
//guess = Int(readLine()!)!
guess = 11
}
print("You guessed a number out of the range!")
//: ## A Custom Expression Pattern with Regex
struct Regex: ExpressibleByStringLiteral, Equatable {
fileprivate let expression: NSRegularExpression
init(stringLiteral: String) {
do {
self.expression = try NSRegularExpression(pattern: stringLiteral, options: [])
} catch {
print("Failed to parse \(stringLiteral) as a regular expression, falling back to match everything")
self.expression = try! NSRegularExpression(pattern: ".*", options: [])
}
}
fileprivate func match(_ input: String) -> Bool {
let result = expression.rangeOfFirstMatch(in: input, options: [], range: NSRange(input.startIndex..., in: input))
return !NSEqualRanges(result, NSMakeRange(NSNotFound, 0))
}
static let email: Regex = """
^(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+)*|\"(?:[\\x01-\\x08\
\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@\
(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0\
-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?\
:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7\
f])+)\\])$
"""
static let phone: Regex = "^(\\+\\d{1,2}\\s)?\\(?\\d{3}\\)?[\\s.-]?\\d{3}[\\s.-]?\\d{4}$"
}
extension Regex {
static func ~=(pattern: Regex, value: String) -> Bool {
return pattern.match(value)
}
}
let input = Bool.random() ? "nerd@bignerdranch.com" : "(770) 817-6373"
switch input {
case Regex.email:
print("Send \(input) and email!")
case Regex.phone:
print("Give Big Nerd Ranch a call at \(input)")
default:
print("An unknown format.")
}
//: ## Switching on a Pointer Value
var emailTextField: UITextField!
var phoneTextField: UITextField!
var passwordTextField: UITextField!
func validateEmail() -> Bool { return false }
func validatePassword() -> Bool { return false }
func validatePhone() -> Bool { return false }
class MyDelegate: NSObject, UITextFieldDelegate {
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
switch textField {
case emailTextField:
return validateEmail()
case phoneTextField:
return validatePhone()
case passwordTextField:
return validatePassword()
default: preconditionFailure("Unaccounted for Text Field")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment