Regex y RegexBuilder en SwiftUI #WWDC22
Regex Builder ha sido presentado en la WWDC22 para poder crear expresiones regular de una manera muy sencilla. En el post de hoy, vamos a extraer hashtags y emails de un texto. Todo lo hacemos con SwiftUI. Vas a ver que con muy pocas líneas de código creamos una funcionalidad muy potente.
Tabla de contenido
Hoy en SwiftBeta vamos a ver un nuevo tipo llamado Regex introducido en la #WWDC22, y lo podemos usar a partir de iOS 16. Con Regex podemos crear expresiones regulares, pero ¿qué significa esto? dentro de grandes (o pequeñas) cantidades de texto, podemos buscar determinadas secuencias. Y ¿cómo podemos buscar estas secuencias? con la expresión regular que generemos.
Imagina que tienes un texto y quieres sacar todos los hashtags que aparecen en él. O tienes un texto de 30 páginas y quieres sacar los correos electrónicos que aparecen en él. Para extraer la información que quieres, solo debes crear la expresión regular con las reglas necesarias. Es decir, si buscas todos los hashtags tendrás que buscar de todas las palabras que hay en el texto la que empiecen por # o si estás buscando todos los correos electrónicos tendrás que buscar un patrón que sea palabra@palabra . com o .es, o el dominio que sea. Pues bien, esto lo vamos a ver en el video de hoy. De un texto sacaremos los hashtags y cuando entendamos el funcionamiento sacaremos los emails. Me ha encantado hacer este video. Y si no tienes ni idea de expresiones regulares, no te preocupes por que te paso estos recursos web sobre expresiones regulares ya creadas para extraer todo tipo de datos. Incluso con toda la explicación para que las adaptes según tu necesidad.
Crear proyecto con Xcode 14
Lo primero de todo que vamos hacer es crear el proyecto en Xcode 14. Recuerda seleccionar como interfaz SwiftUI.
Regex expresiones regular en SwiftUI
Una vez creado nuestro proyecto en Xcode, vamos a crear una variable text, dentro de esta variable añadiremos un texto random, podéis copiar y pegar el que añadiré a continuación, dentro de esta variable analizaremos en busca de hashtags con nuestra expresión regular:
struct RegexView: View {
@State private var text = "#qwoieiewquewquieoqwueqw qwej #swift wehew ijhq wn dasjkdsahdsjah qiuh qweuh eqow #swiftbeta #wwdc22 [email protected] anojdfasofi [email protected] adodais js #swiftui adioadsa adsihadsusaduioas."
@State private var hashTags = ""
var body: some View {
Form {
Section {
Text(text)
Button("Get Hashtags") {
//TODO
}
}
Section {
Text(hashTags)
}
}
}
}
Hemos creado un Form con distintas secciones, en la primer asección tenemos nuestro texto de la variable text, y un button.
Extraer hashtags con Regex en SwiftUI
Cuando se pulse el button se mostrará en la siguiente sección del Form todos los hashtags detectados en la propiedad text. Ahora vamos a crear el método con toda la lógica:
func checkHashTags() {
let regex = try! Regex("#[a-z0-9]+")
let match = text.matches(of: regex)
match.forEach { value in
let lowerBounds = value.range.lowerBound
let upperBounds = value.range.upperBound
let hashTag = text[lowerBounds...upperBounds]
print(hashTag)
hashTags.append(String(hashTag))
}
}
Esta función hace varias cosas:
- Crea la expresión regular para extraer los hashtags de nuestro texto. Como hemos dicho antes, es nuestra fórmula que irá comprobando en la propiedad text si se cumple nuestra expresión regular. Más tarde la modificaremos para que veas que se pueden extraer hashtags de nuestro texto con otras expresiones regulares.
- Comprobamos si nuestra expresion regular tiene las coincidencias que buscamos en nuestra propiedad text
- Si hay coincidencias extraemos la palabra completa y la añadimos al array de hashTags para mostrar en la segunda sección de nuestro Form.
Vamos a compilar y vamos a ver si funciona. Al pulsar el Button de nuestro Form vemos como nuestra expresión regular ha sido capaz de extraer 🙌.
Ahora vamos hacer una pequeña prueba y vamos a modificar nuestra expresión regular, vamos a remplazar la constante regex por el siguiente contenido:
let regex = /#\w+/
Fíjate que curioso que no hace falta meterlo entre comillas ni ningún otro caracter. Xcode sabe como gestionar las expresiones regulares al estar entre las barras /. Si compilamos y apretamos el Button, vemos que funciona igual que antes.
Refactor Regex Builder en SwiftUI
Incluso podemos utilizar otra sintaxis al programar nuestra expresiones regular en Xcode. Del anterior ejemplo, podemos utilizar el nuevo Regex Builder que nos permite crear expresiones regular con un propio DSL de Apple.
Si compilamos nuestra app y pulsamos el Button, vemos que sigue funcionando sin problemas.
Incluso, podemos comentar nuestra constante regex y crear una nueva de la siguiente manera:
let regex = try! Regex {
"#"
ZeroOrMore {
CharacterClass("a"..."z", "A"..."Z", "0"..."9")
}
}
La verdad es que es brutal el poder crear expresiones regulares de esta manera. Si compilamos y apretamos el Button, vemos que sigue funcionando perfectamente nuestra expresión regular.
Extraer correos electrónicos con Regex en SwiftUI
Lo que vamos hacer a continuación es crear otra expresión regular para extraer correos electrónicos de un texto. Vamos a utilizar el mismo texto, lo único que vamos a crear una propiedad nueva y método nuevo:
import SwiftUI
import RegexBuilder
struct RegexView: View {
@State private var text = "#qwoieiewquewquieoqwueqw qwej #swift wehew ijhq wn dasjkdsahdsjah qiuh qweuh eqow #swiftbeta #wwdc22 [email protected] anojdfasofi [email protected] adodais js #swiftui adioadsa adsihadsusaduioas."
@State private var hashTags = ""
@State private var emails = ""
var body: some View {
Form {
Section {
Text(text)
Button("Get Hashtags & Emails") {
checkHashTags()
checkEmails()
}
}
Section("HASHTAGS") {
Text(hashTags)
}
Section("EMAILS") {
Text(emails)
}
}
}
func checkHashTags() {
let regex = try! Regex {
"#"
ZeroOrMore {
CharacterClass("a"..."z", "A"..."Z", "0"..."9")
}
}
let match = text.matches(of: regex)
match.forEach { value in
let lowerBounds = value.range.lowerBound
let upperBounds = value.range.upperBound
let hashTag = text[lowerBounds...upperBounds]
print(hashTag)
hashTags.append(String(hashTag))
}
}
func checkEmails() {
let regex = /\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b/
let match = text.matches(of: regex)
match.forEach { value in
let lowerBounds = value.range.lowerBound
let upperBounds = value.range.upperBound
let email = text[lowerBounds...upperBounds]
print(email)
emails.append(String(email))
}
}
}
Sencillo verdad? hemos visto una pincelada de lo que podemos hacer con Regex en SwiftUI. La verdad que muy potente y muy contento de aprender estas nuevas APIs.