Saltar al contenido →

NSScanner

Tengo que reconocer que soy un gran fan del uso de las Expresiones Regulares. Son quizá uno de los mejores amigos para cualquier desarrollador pero a veces el continente de la información no justifica su uso debido a su falta de formato.

Es entonces cuando entra en juego otro gran amigo de los desarrolladores para sistemas Apple, y no es otro que la clase NSScanner o Scanner.

¿En qué se diferencia Scanner de una Expresión Regular?

Básicamente en que las expresiones regulares son fantásticas cuando las cadenas de texto que queremos extraer/validar están incluidas en un formato determinado y conocido, como por ejemplo un archivo CSV en el que conocemos de antemano que es cada columna, de que tipo es y en que formato está.

Ahora vamos a imaginar que queremos procesar las etiquetas y usuarios que aparecen en un tuit cualquiera. Un tuit no tiene formato ninguno, no sabemos qué posición ocupa lo que buscamos o si tan siquiera puede estar presente.

Es en estos casos en los que Scanner se convertirá en nuestra nuevo más mejor amigo dentro del framework Foundation.

Ahora explícame cómo uso Scanner.

An NSScanner object interprets and converts the characters of an NSString object into number and string values. You assign the scanner’s string on creating it, and the scanner progresses through the characters of that string from beginning to end as you request items.

Lo primero que hay que saber es que Scanner trabaja con String y con CharacterSet. El primero es conocido por todos, una cadena de texto. El segundo es un representación de los conjuntos de caracteres Unicode, o de uno definido por nosotros.

Y lo que necesitamos saber antes de usar Scanner es…

  1. La cadena de texto en la que vamos a buscar — String
  2. Como empieza lo que queremos buscar — CharacterSet
  3. Como termina lo que queremos buscar— CharacterSet

Vamos a utilizar un tuit como ejemplo para ir explicando la configuración y uso de la clase Scanner. En el ejemplo vamos a extraer todas las etiquetas y usuarios mencionados.

Scanner realiza una lectura secuencial de la cadena de texto en busca de los caracteres en los que estamos interesados. En este caso queremos que nos informe cuando encuentre una etiqueta (#) o un usuario (@). Este es el CharacterSet de los que nos interesa encontrar.

Ahora que Scanner sabe como empieza el texto que nos interesa tendremos que decir como termina. En el caso de las etiquetas y los nombre de usuario terminan cuando aparece un espacio en blanco o un signo de puntuación. Así que este es el CharacterSet con el que terminará de nuestra búsqueda

Lo que hacemos en las líneas 5 y 6 es construir el CharacterSet con los caracteres que marcan en final de una etiqueta o nombre de usuario, en este caso espacios en blanco, nuevas líneas de texto ( CharacterSet.whitespacesAndNewlines) y los signos de puntuación (CharacterSet.punctuationCharacters)

En la línea 8 creamos el CharacterSet con los caracteres que indican el comienzo de una etiqueta (#) o nombre de usuario (@)

En la línea 13 comienza el bucle que procesa cada uno de los elementos que Scanner encuentra en el tuit hasta que llega al final de éste. Viene indicando por el valor de la propiedad atEnd de tipo Bool.

Dentro del bucle lo que pasa es que vamos escaneado hasta encontrar el carácter de etiqueta o usuario. Esto lo hacemos con el método scanUpToCharactersFromSet que devuelve un String con el texto encontrado hasta ese momento, lo obviamos porque no lo que nos interesa.

Una vez que tenemos el Scanner situado sobre una etiqueta o usuario le decimos que avance hasta que encuentre uno de los caracteres que marcan su final. Esto lo que conseguimos nuevamente con el método scanUpToCharactersFromSet que nos devolverá el texto que va desde la posición anterior de Scanner, la del símbolo # o @, hasta la posición actual.

De esta manera obtenemos una etiqueta o nombre de usuario. Y el bucle se repite hasta que llega al final de la cadena de texto con el tuit.

Enlaces de interés

Publicado en Swift

Comentarios

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *