Configuración y traducción de una aplicación de iOS

En la entrega anterior del Curso de Aplicaciones de iOSvimos como guardar datos persistentes, pero ¿qué pasa si lo que queremos guardar son de muchos tipos y en distintas partes del código?, ¿escribimos una clase con métodos estáticos que acceda a un modelo de datos configuración con valores transformables?…vale, esto se podría hacer pero tenemos una opción más sencilla y que además se puede utilizar en la interfaz de configuración del propio iOS especialmente dedicada a nuestra aplicación.

Preferencias de la aplicación iOS

Un mundo en un diccionario

Estamos hablando de las preferencias por defecto del usuario. En otras palabras, vamos a usar la clase NSUserDefaults, que accede las preferencias que creemos o bien por código o bien con el diseñador de “Settings Bundle”, estas quedan almacenadas en un fichero plist (xml), donde se define cada elemento como un diccionario que contiene los diferentes parámetros en tipos de datos que son diccionarios internamente.

Ejemplo de creación: File -> New File -> Resource -> Settings Bundle.

Normalmente el nombre que se le suele dar al fichero es “Root.plis”, la edición dentro de XCode de este tipo de ficheros de configuración viene a ser algo así:

Estos diccionarios tienen unos tipos de atributos, los siguientes:

  • Type: tipo de la preferencia
  • Title: título de la preferencia, se utiliza para codificar las traducciones también (en lugar de Key)
  • Key: clave para recuperar la preferencia desde el código
  • DefaultValue: valor por defecto
  • IsSecure: se utiliza para campos de texto como contraseñas
  • KeyboardType: tipo de teclado, puede ser Alphabet, NumbersAndPunctuation, NumberPad, URL y EmailAddress (al igual que en las preferencias de Interface Builders para campos de texto)
  • AutocapitalizationType: se especifica como None, Sentences o Words y convierte lo elegido a mayúsculas
  • AutocorrectionType: si se pone como Yes entonces se utiliza el corrector automático de iOS en el campo

Veréis que existen varios tipos de datos a la hora de añadir un diccionario que contiene un elemento de preferencias, estos tipos pueden ser:

  • PSTextFieldSpecifier: campo de texto, para un usuario o password, o cualquier otro posible uso
  • PSTitleValueSpecifier: es un título, de sólo lectura, puede preceder a otro campo que no tenga título propio
  • PSToggleSwitchSpecifier: elemento ON/OFF, es decir, puede servir como booleano
  • PSSliderSpecifier: campo sin título, sirve para establecer un valor numérico con una escala, tiene un máximo y un mínimo, además del valor por defecto también podemos especificar una imagen para cada lado de los límites
  • PSMultiValueSpecifier: sirve para mostrar una lista de valores entre los que podemos elegir
  • PSGroupSpecifier: una manera elegante de separar cada zona de configuración haciendo un grupo (o subgrupo)
  • PSChildPaneSpecifier: al pinchar en este campo se abrirá una nueva página de configuraciones asociada (otro plist)
Aquí un ejemplo de las opciones:
En el caso que utilicemos un panel hijo el esquema sería algo parecido a esto:
Siempre podemos acceder a las opciones a través de la clase NSUserDefaults ,de la misma manera que funciona un diccionario (como un NSMutableSet), los objetos que guardemos tienen que ser serializables, como ocurría con el modelo de datos para poder utilizarse como un valor. En concreto, las preferencias se guardan desde NSUserDefaults -> standardUserDefaults, si creamos campos de preferencias para usuario,nivel, nombre y otro de password el código a usar es así:`

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
 
NSString *strUser = [defaults objectForKey:@"usuario"];
int level = [[defaults objectForKey:@"nivel"] intValue];
NSString *strName = [defaults objectForKey:@"nombre"];
NSString *strPass = [defaults objectForKey:@"password"];

Si cargamos la aplicación por primera vez, debemos guardar los valores, igual que antes pero usando la función

[[NSUserDefaults standardUserDefaults] setValue:(id) forKey:(NSString*)];

[NSUserDefaults standardUserDefaults] synchronize]; //imprescindible!

,evidentemente, si los tipos de datos son numéricos, tenemos que encapsularlos en una clase NSNumber, etc.

Para reiniciar los valores en el simulador (esto debemos hacerlo también para cuando cambiemos un fichero traducido de Interface Builder) , borramos el directorio ~/Library/Application Support/iPhone Simulator/User/Applications o bien, abrimos el simulador, y borramos la aplicación o por último, en el menú del simulador – > Restablecer contenidos y ajustes. Esta última opción borrará todas las compilaciones de XIB a NIB (ficheros de I.B.).

Info.plist

Este fichero, según la documentación de XCode, contiene la información de configuración de la aplicación (en un bundle), puede utilizarse para especificar el icono de la aplicación, incluso una cadena “audio” en la variable UIBackgroundModes para cuando la aplicación pasa a segundo plano y estamos haciendo streaming ,que no se corte.

O se puede indicar con la cadena “voip” para que se use un socket para VoIP (luego hace falta que se invoque al método setKeepAliveTimeout: handler para especificar la frecuencia con la que despertar la aplicación para que funcione bien la aplicación, por ejemplo, para cargar el buffer que se está reproduciendo).

Más información >

Traducciones de aplicaciones de iOS

Más diccionarios en ficheros de texto

Para realizar las traducciones utilizamos dos aplicaciones de XCode que extraen las cadenas de texto a traducir a todos los idiomas: ( ver recursos de traducción> ),

  • genstrings: extrae de los ficheros .m todos los usos de la función NSLocalizedString(@”LLAVE”, @”COMENTARIO PARA SABER DE QUÉ VA LA TRADUCCIÓN DE LA LLAVE EN SU SITIO”).
    En el código reemplazamos todas las cadenas a traducir @”Mi Cadena” , por NSLocalizedString(@”miCadenaX”, “Mi Cadena”)…fácil…
    Ejemplo de uso:, desde ~directorioDeMiProyecto$
    [sourcecode language=”bash”]
    genstrings -o es.lproj *.m

    toma como entrada todos los ficheros de implementación y busca NSLocalizedString, creando un fichero codificado con el juego de caracteres UTF-16 con líneas así:
    /* Comentario de la llave */
    “llave” = “Texto para la llave”;
    Una vez generados los ficheros para los .m en cada idioma, pues se traducen y luego se deben añadir los directorios al proyecto, si véis que no coge las cadenas de texto, quitad los directorios (en.lproj) sin borrarlos ,sólo la referencia, y luego añadirlos de nuevo

  • Truco para traducir los títulos de las preferencias (la configuración) de la aplicación: cuando creamos nuestro Settings.bundle ,dentro aparece un fichero llamado Root.plist , pues bien, vamos a crear un nuevo fichero en el proyecto ,de tipo Resource -> Strings File, le llamamos, claro, Root.plist, cuando nos pregunte si queremos sobreescribir le diremos que sí, después, en la ventana de inspección, en la pestaña de Localization añadimos los idiomas.
  •  ibtools:  Haremos lo mismo que en con el truco anterior, en la pestaña de Localization añadimos los idiomas a utilizar, después podemos usar una instrucción como esta para extraer todas las cadenas de texto (si no queremos traducir todo a mano con el editor del Interface Builder,claro), una vez añadidos los idiomas:
    [sourcecode language=”bash”]
    ibtool –generate-strings-file en.lproj/MiFichero.strings en.lproj/MiFichero.xib

    En el fichero strings estarán las cadenas de texto a traducir, una vez hecho, las escribimos de nuevo al .xib:

    [sourcecode language=”bash”]
    ibtool –write MiFichero.strings MiFichero.xib

    Más información de XCode 4 y ibtool >

Los strings se pueden enviar a empresas de traducción para que hagan su trabajo y luego con esos pasos ya está todo hecho. Para probar que los idiomas funcionan sólo hay que ir a la configuración del iDevice y cambiar en los Ajustes Generales el idioma en Internacional.

<< Volver al Curso de Aplicaciones de iOS
|| Ir al siguiente capítulo: Geolocalización con MapKit de Google y CoreLocation »

Artículos relacionados:

Please type the characters of this captcha image in the input box

Por favor escriba los caracteres de la imagen captcha en el cuadro de entrada

footer
jbelon © | sitemap.xml