Forked from JulianAlonso/Regex&Matcher-Playground.swift
Created
August 31, 2022 13:27
-
-
Save sbhmajd/b991979afad394c01d6f48a43146a667 to your computer and use it in GitHub Desktop.
Mapping URL (Deep linking) on iOS.
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 | |
extension String { | |
//Know if self is only composed by numbers | |
var isNumber: Bool { | |
return !self.isEmpty && CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: self)) | |
} | |
} | |
//Struct to check Regular Expresions | |
struct Regex { | |
let pattern: String | |
let options: NSRegularExpression.Options! | |
private var matcher: NSRegularExpression { | |
return try! NSRegularExpression(pattern: self.pattern, options: self.options) | |
} | |
init(_ pattern: String, options: NSRegularExpression.Options = [.caseInsensitive]) { | |
self.pattern = pattern | |
self.options = options | |
} | |
//Devuelve el array de grupos | |
func match(_ string: String, options: NSRegularExpression.MatchingOptions = []) -> [NSTextCheckingResult] { | |
return self.matcher.matches(in: string, options: [], range: NSMakeRange(0, string.characters.count)) | |
} | |
} | |
//Implement this in whatever type you want to check with regular expresions | |
protocol RegexMatchable { | |
func match(regex: Regex) -> Bool | |
} | |
//Wrap the comparing string and the groups to extract ids | |
final class Matcher: RegexMatchable { | |
let comparing: String | |
var groups: [NSTextCheckingResult]? | |
var matchingGroups: [String] { | |
var matches = [String]() | |
if let groups = groups { | |
let string = comparing as NSString | |
for group in groups { | |
for index in 1..<group.numberOfRanges { | |
matches.append(string.substring(with: group.rangeAt(index))) | |
} | |
} | |
} | |
return matches | |
} | |
var intGroups: [Int] { | |
return self.matchingGroups.flatMap { Int($0) } | |
} | |
init(_ matching: String) { | |
self.matching = matching | |
} | |
func match(regex: Regex) -> Bool { | |
let matches = regex.match(self.matching) | |
if !matches.isEmpty { | |
self.groups = matches | |
return true | |
} | |
return false | |
} | |
} | |
extension String: RegexMatchable { | |
func match(regex: Regex) -> Bool { | |
return !regex.match(self).isEmpty | |
} | |
} | |
//Overload patter matching operator | |
func ~=<T>(pattern: Regex, matchable: T) -> Bool where T: RegexMatchable { | |
return matchable.match(regex: pattern) | |
} | |
//Routing with enums its easy | |
enum DeepLinking { | |
case helado(id: Int) | |
} | |
func linking(_ path: String) -> DeepLinking? { | |
let matching = Matcher(path) | |
switch matching { | |
case Regex("^(\\/helado\\/([0-9]+)\\/*)"): | |
guard let id = matching.intGroups.first else { return nil } | |
//Here you have your id, typed. | |
return .helado(id: id) | |
default: | |
//No matches | |
return nil | |
} | |
} | |
let link = linking("/helado/43") //.helado(43) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment