Forked from JulianAlonso/Regex&Matcher-Playground.swift
Created
March 7, 2023 06:22
-
-
Save hsleedevelop/04cbfc15bf0c68863915288419ea0f0b 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