Vistas de página en total

jueves, 29 de junio de 2017

Navegación entre páginas

En este artículo vamos a construir una sencilla aplicación con múltiples páginas. Aprenderemos cómo navegar entre pantallas y cómo tratar eventos de la UI. En siguientes artículos iremos desarrollando poco a poco esta aplicación. No es el objetivo de este ejemplo la apariencia o usabilidad de la aplicación, así que no nos detendremos en los aspectos gráficos de la UI.

Definición de la aplicación

Esta sencilla aplicación consta de dos páginas:
  • home
  • about
La página home será la primera página que vean los usuarios al lanzar la aplicación. La página about mostrará información textual sobre la aplicación.

Creación del proyecto vacío

Para crear el proyecto utilizamos el CLI de Nativescript, como siempre:
    tns create TechnoShop --appid com.joseanquiles.technoshop
Ahora vaciamos el proyecto, para empezar desde cero:
Borrar el fichero app/bundle-config.js
Borrar el fichero app/main-view-model.js
Borrar el fichero app/main-page.xml
Borrar el fichero app/main-page.js
Abrir el fichero app/app.js y dejarlo como sigue:
var application = require("application");
application.cssFile = "./app.css";
application.start({ moduleName: "views/home-page" });
Crear carpeta app/views
Crear fichero app/views/home-page.xml y rellenarla con lo siguiente:
<Page>
</Page>
Page es un contenedor de todos los elementos de la página. Es el elemento padre de todos los demás elementos de la página.
Ejecutar el proyecto:
    cd TechnoShop
    tns platform add android
    tns run android --emulator
Si todo ha ido bien, tendremos una aplicación vacía ejecutándose en el emulador.

Añadir contenido a la página home

Vamos a poner una etiqueta de bienvenida en home-page.xml:

<Page>
    <StackLayout>
        <Label text="Bienvenido a TechnoShop!" />
    </StackLayout>
</Page>

StackLayout es un contenedor que sitúa a sus elementos hijos uno encima de otro. Los contenedores se llaman layouts en Nativescript. En otros artículos veremos otros tipos de layouts que permiten organizar a sus hijos de otras formas.
Label es una etiqueta de texto. El atributo text define el texto que muestra la etiqueta.

Crear la página about

Crear fichero app/views/about-page.xml  y rellenarla con lo siguiente:

<Page>
    <StackLayout>
        <Label text="TechnoShop, la tienda de tecnología online. Tenemos todo tipo de dispositivos y accesorios para ti" />
        <Label text="Madrid (España)" />
    </StackLayout>
</Page>
Si ejecutamos la aplicación ahora, nos daremos cuenta de que no hay forma de ver la nueva página que hemos creado.
Podríamos cambiar la página de arranque en app.js para que apunte a home-page, así podremos ver la nueva página:
    application.start({ moduleName: "views/about-page" });
Ahora sí podemos ver la página About. Lo primero que vemos es que el texto de la primera etiqueta está recortado, porque no cabe en el ancho del móvil. Para resolver este problema, utilizamos el atributo textWrap de Label.

    <Label textWrap="true" text="TechnoShop, la tienda de tecnología online. Tenemos todo tipo de dispositivos y accesorios para ti" />

Gracias a poner textWrap="true" el texto que no cabe en una línea pasará a la siguiente línea.
Y ahora, vamos a volver a poner home-page como página de inicio:

application.start({ moduleName: "views/home-page" });

Implementemos la navegación entre páginas...

Navegación entre páginas

Hasta ahora hemos ido construyendo páginas en su correspondiente fichero xml, pero no hemos añadido ninguna lógica a estas paginas. La lógica de las páginas va en el fichero .js asociado a cada página.
La navegación entre páginas ocurre en respuesta a una acción sobre un elemento de la página (por ejemplo, pulsando un botón). La acción asociada está en el fichero .js de la página.

Añadir un botón a la página home

La etiqueta Button inserta un botón en la página Home:

<Page>
    <StackLayout>
        <Label text="Bienvenido a TechnoShop!" />
        <Button text="Acerca de..." tap="onAbout" />
    </StackLayout>
</Page>

El atributo text de Button especifica el texto que mostrará el botón.
El atributo tap de Button especifica la función javascript que se ejecutará cuando se pulse el botón.

Tratar el evento tap

El evento tap de Button se produce al pulsar el botón. La función que hemos especificado para tratar este evento se llama onAbout y hay que definirla en el fichero javascript asociado a la página. El fichero que tenemos que crear es app/views/home-page.js

var frame = require("ui/frame");
function onAbout() {
    frame.topmost().navigate("views/about-page");
}
exports.onAbout = onAbout;

El módulo ui/frame se utiliza para navegar entre páginas. Este módulo se incluye en los core-modules de Nativescript.
La función onAbout() se ejecutará cuando se produzca el evento tap en el Button.
Por último, tenemos que exportar la función añadiéndola al objeto exports.

Una forma más breve de hacer lo mismo sería:

var frame = require("ui/frame");
exports.onAbout = function() {
    frame.topmost().navigate("views/about-page");
}

Si ejecutamos la aplicación veremos el botón debajo del texto de bienvenida. Si pulsamos el botón, pasaremos a la página About.

Aplicar transiciones

Una transición es una animación que ocurre cuando se navega de una página a otra.
Nativescript nos ofrece una serie de transiciones predefinidas que podemos utilizar tanto en iOS como en Android:
  • fade
  • flipRight
  • flipLeft
  • slideLeft
  • slideRight
  • slideTop
  • slideBottom
Para aplicar la transición, cambiaremos home-page.js de la siguiente forma:

var frame = require("ui/frame");
exports.onAbout = function() {
    var nav = {
        moduleName : "views/about-page",
        transition : {
            name : "slideBottom",
            duration : 2000
        }
    };
    frame.topmost().navigate(nav);
}

En este caso, hemos creado un objeto llamado nav que incluye la página a la que se navega (moduleName) y un objeto transition que define la transición (name y duration en milisegundos).






miércoles, 28 de junio de 2017

Programando para diversas plataformas y tamaños

Aunque Nativescript es un framework multiplataforma y el objetivo es que una aplicación Android e iOS compartan el máximo de código, la realidad es que en ocasiones queremos que la UI sea algo diferente en cada plataforma, e incluso que la lógica de la aplicación sea específica para una plataforma. Un ejemplo podría ser el uso de touch-id: en iOS podríamos autenticar al usuario con touch-id, pero en Android pediríamos usuario y password.


Nativescript proporciona varios mecanismos para hacer UI y lógica de aplicación específicos para cada plataforma y para cada tamaño.

Código específico de cada plataforma

XML específico de una plataforma

La primera forma de definir un UI específico para cada plataforma es separar el fichero.xml de una página en dos ficheros, uno para el UI de Android y otro para el UI de iOS. Para diferenciar los dos ficheros, añadimos .android o .ios al nombre del fichero:
  • main-page.android.xml
  • main-page.ios.xml
Esta aproximación es sencilla, pero obliga a duplicar el UI de la página para cada plataforma. Esto es bastante engorroso si sólo queremos un pequeño cambio de un UI a otro, ya que tendremos que duplicar casi todo el layout de la página. En este caso en que sólo queremos un pequeño cambio, tenemos una solución mucho mejor: mantener un fichero común y poner markup específico de cada plataforma:
    <StackLayout>
        <Button text="Este botón sale en ambas plataformas" />
        <android>
            <Button text="este texto sólo se muestra en android" />
        </android>
        <ios>
            <Button text="este texto sólo se muestra en ios" />
        </ios>
    </StackLayout>

Javascript específico de una plataforma

Al igual que ocurre con los fichero xml, también podemos utilizar la notacion .android y .ios en los ficheros javascript. Pero además, disponemos de la notación .common:
  • main-page.common.js
  • main-page.android.js
  • main-page.ios.js
En primer lugar, se carga el fichero .common y después se carga el fichero específico de la plataforma.
Además, Nativescript nos proporciona dos variables globales javascript: 'android' e 'ios', que nos indican la plataforma en la que estamos ejecutando. Utilizando estas variables podemos evitar partir el código javascript en 3 ficheros diferentes:
    if (android) {
        ......
    }
    if (ios) {
        ........
    }

Estilos específicos por plataforma

Para separar estilos por plataforma se utiliza el mismo criterio utilizado en XML:
  • main-page.android.css
  • main-page.ios.css

Código específico de cada tamaño

Device independent pixels

Los device independent pixels, o dp, son una forma de describir el tamaño físico de un dispositivo (ancho y alto) de la pantalla del dispositivo, sin decir el número de pixels que tiene.
En general, Android e iOS clasifican sus pantallas como si tuvieran 160 dp por pulgada (esto es aproximado, cada plataforma tiene un valor distinto). Así, podemos asumir que si un dispositivo tiene un ancho mayor de 600 dp, entonces es una tablet, ya que 600/160=3.75 pulgadas=9.5 cm. Si tiene un ancho menor de 600 dp entonces es un teléfono. En general, los dp son una forma de medir el tamaño físico de la pantalla.

Convención de nombres de fichero para distintos tamaños

Para utilizar ficheros específicos para distintos tamaños, se añaden los siguientes sufijos al nombre del fichero:
  • .minWxxx : si el ancho del dispositivo es al menos xxx dp
  • .minHxxx : si el alto del dispositivo es al menos xxx dp
  • .minWHxxx : si la más pequeña de las dimensiones del dispositivo es al menos xxx dp
Por ejemplo, si tenemos los ficheros main-page.xml y main-page.minWH600.xml, éste último se mostraría en una tablet y el primero en un teléfono, ya que la dimensión menor de una tablet es superior a 600 dp, como hemos  dicho antes.

Orientación del dispositivo

Otra necesidad muy común cuando se desarrollan aplicaciones es tener un UI distinto en función de la orientación del dispositivo. Para ello Nativescript nos ofrece la siguiente convención de nombres:
  • .land : para orientación landscape u horizontal
  • .port : para orientación portrait o vertical

Encadenando restricciones

Hasta ahora hemos visto cómo aplicar una única restricción en la convención de nombres de fichero: plataforma, tamaño mínimo, orientación. ¿Cómo podemos aplicar varias restricciones a la vez? En Nativescript esto es tan sencillo como encadenar. Por ejemplo, main-page.android.land.xml se aplica a la plataforma android en orientación landscape. El orden de las restricciones no importa, Nativescript aplicará lo que corresponda sin importar el orden.

Anatomía de una aplicación Nativescript

Nativescript sigue la filosofía de obligar a unas determinadas convenciones, tanto en la estructura de directorios y ficheros, como a los nombres de éstos. Nativescript es dogmático en el sentido de que tenemos que escribir el código, nombrar los ficheros/directorios y organizar los componentes de cierta forma, obligatoriamente. Si no se siguen estas reglas, la aplicación no se ejecutará.

Esto tiene ventajas e inconvenientes. El principal inconveniente es que no deja lugar a la creatividad del programador. Pero todo lo demás son ventajas, sobre todo, el hecho de que cualquier programador que herede una aplicación Nativescript puede comprender rápidamente su estructura.

Estructura de la aplicación
Cuando creamos una aplicación con tns create appname, el CLI crea una serie de directorios:
    /appname
        /app
            .xml, .js, .css
            references.d.ts
            app.js y app.css
            /App_Resources
                /Android
                /iOS
        /node_modules
        /platforms
            /android
            /ios
        package.json
En principio, y salvo excepciones, el programador sólo debe modificar lo que hay debajo del directorio /app.

package.json

El fichero package.json que hay en el directorio raíz de la aplicación contiene algunas características de la aplicación y dependencias.

{
    "description": "NativeScript Application",
    "license": "SEE LICENSE IN <your-license-filename>",
    "readme": "NativeScript Application",
    "repository": "<fill-your-repository-here>",
    "nativescript": {
        "id": "com.joseanquiles.mylistview",
        "tns-ios": {
            "version": "3.1.0"
        },
        "tns-android": {
            "version": "3.1.1"
        }
    },
    "dependencies": {
        "nativescript-theme-core": "~1.0.2",
        "tns-core-modules": "3.1.0"
    },
    "devDependencies": {
        "babel-traverse": "6.25.0",
        "babel-types": "6.25.0",
        "babylon": "6.17.4",
        "lazy": "1.0.11"
    }
}
La sección nativescript.id contiene el identificador único de la aplicación. Este identificador se utiliza cuando se construye la aplicación para iOS o Android, y cuando la subamos a los market correspondientes: AppStore, Google Play. Podemos definir este identificador al crear la aplicación con el parámetro --appid. También se puede cambiar después editando el fichero package.json, pero entonces tendremos que eliminar las plataformas, añadirlas y volver a construir la aplicación.
La sección dependencies indica una serie de paquetes npm (y su versión) que utiliza la aplicación. Al menos, siempre tendremos la dependencia tns-core-modules.

node_modules

El directorio node_modules está relacionado directamente con el fichero package.json. Contiene una copia local de los módulos de los cuales depende la aplicación.
Durante el desarrollo de la aplicación, se puede utilizar npm para añadir módulos a la aplicación, los cuales se meterán en este directorio.

platforms

Después de crear la aplicación, este directorio está vacío. Se rellena cuando se ejecuta el comando tns platform add android (ios).
Contiene ficheros que son necesarios para el despliegue de la aplicación tanto en emulador como en dispositivo.

app

En el directorio app están los ficheros que componen la aplicación: xml, js y css.

app/App_Resources

El directorio App_Resources tiene dos subdirectorios: Android e iOS. En estos directorios se guardan ficheros específicos para cada una de las plataformas. Por ejemplo, en Android se guardan ficheros que sólo necesita la plataforma Android.
En cierto sentido, los directorios platforms y App_Resources son similares, porque contienen ficheros específicos de cada plataforma. Sin embargo, los ficheros del directorio platforms no los podemos modificar, y los de App_Resources sí.
Cada vez que se modifique algo debajo del directorio App_Resources es necesario ejecutar tns prepare android (o ios). Este comando lee los cambios realizados y los pasa al directorio platforms.

references.d.ts

Este fichero sólo se utiliza si empleamos Typescript como lenguaje de programación (en lugar Javascript).
En este fichero se guarda información útil para los IDEs (autocompletado, chequeos, etc).

Ficheros .xml .css y .js

Cada página de nuestra aplicación se compone de 3 ficheros (aunque podrían ser menos si alguno no se utiliza). Los tres ficheros tienen el mismo nombre y se distinguen por la extensión, por ejemplo: edit_user.xml, edit_user.css y edit_user.js
El fichero .xml contiene el layout y los controles de UI de la página.
El fichero .css contiene estilos específicos de la página (sólo se aplican a esta página).
El fichero .js contiene el código javascript con la lógica (inicialización, manejo de los eventos, etc).

app/package.json

Este fichero no tiene nada que ver con package.json que encontramos en el directorio raíz de la aplicación. En este caso, se describe la configuración y contenido del directorio app.
El directorio app es realmente un paquete npm y por tanto, se requiere el fichero package.json para describir el paquete npm.
El comando tns create, internamente descarga e instala un paquete npm llamado tns-template-hello-world en el directorio apphttps://www.npmjs.com/package/tns-template-hello-world
El fichero app/package.json contiene en main el fichero .js que es el punto de entrada de la aplicación (normalmente el fichero app.js).

app.js y app.css

El fichero app.js es el punto de entrada de la aplicación (tal y como se define en app/package.json).
El fichero app.css contiene definiciones de estilos que se aplican a toda la aplicación.
El fichero app.js contiene el código que arranca la aplicación:
    vap application = require("application");
    application.start( { moduleName : "main-page" } );
La primera línea carga el módulo "application" (este módulo tiene métodos para manejar la aplicación).
La segunda línea indica a Nativescript que cargue y ejecute una página llamada "main-page" (la cual puede estar definida en los tres ficheros main-page.xml, main-page.js y main-page.css).

ListView en Nativescript

En este tutorial vamos a crear una pequeña aplicación utilizando el potente control ListView de Nativescript. El objetivo no es entender todo el código al 100%, sino ver las posibilidades que ofrece este framework. En posteriores tutoriales iremos creando aplicaciones donde se comprenderá perfectamente todo el código, pero no es el objetivo ahora.

En primer lugar, creamos el proyecto Nativescript:
    tns create MyListView --appid es.indra.nativescript.listview
 
La opción --appid permite poner un identificador a la aplicación que se utilizará posteriormente en las tiendas de aplicaciones: Play store y App store. Se puede cambiar después de creado el proyecto, pero entonces habría que quitar y volver a añadir las plataformas Android e iOS.
A partir de ahora y para simplificar, me referiré a los ficheros a partir del root del proyecto. Por ejemplo, me referiré al fichero MyListView/app/app.js como app/app.js

Partir de un proyecto vacío

El esqueleto que crea el CLI de Nativescript incluye código y ficheros que no necesitamos en un proyecto nuevo. Vamos a vaciar este esqueleto y lo dejamos preparado para empezar.

Borrar el fichero app/bundle-config.js (no es necesario salvo que se utilice Angular con Nativescript).
Borrar el fichero app/main-view-model.js (crearemos el modelo directamente en la página, ya que es un ejemplo muy sencillo).
Abrir el fichero app/app.js y quitar la línea:
    require("./bundle-config");
 
Vaciar el fichero app/main-page.js y dejarlo así:
    exports.onLoaded = function(args) {
        var page = args.object;
        page.bindingContext = {};
    }
Vaciar el fichero app/main-page.xml y dejarlo así:
    <Page loaded="onLoaded" class="page">
    </Page>
Ya tenemos un proyecto vacío, listo para empezar a trabajar. Ejecutemos el proyecto vacío para comprobar que todo ha ido bien:
    cd MyListView
    tns platform add android 
    tns platform add ios              (esto sólo es posible en un ordenador con MacOS)
    (si queremos ejecutar en genymotion, hay que arrancarlo ahora, antes del comando run)
    tns run android --emulator
    tns run ios --emulator
 
La primera vez que lo ejecutemos puede tardar incluso varios minutos en lanzarse la aplicación en el emulador, pero las siguientes modificaciones que vayamos haciendo refrescarán la aplicación rápidamente. Cuando veamos la aplicación en el emulador, veremos una pantalla en blanco (en el caso de Android veremos el nombre de la aplicación en la parte superior de la pantalla).



Lo primero que vamos a hacer es crear el modelo para la página. En el fichero app/main-view.js modificamos la línea donde se crea el bindingContext para dejarla así:
    page.bindingContext = {
        elements: [
            { 'name':'Indra', 'website':'http://www.indra.es' },
            { 'name':'Telefonica', 'website':'http://www.telefonica.com' }
        ]
    };
 
page.bindingContext es el modelo de datos al que accede la vista en el xml, como ahora veremos.
Situemos el control ListView en el fichero app/main-view.xml:
    <Page loaded="onLoaded" class="page">
        <ListView id="list" items="{{ elements }}">
            <ListView.itemTemplate>
                <StackLayout>
                    <Label text="{{ name || 'unknown name' }}" class="itemName" />
                    <Label text="{{ website || 'unknown website' }}" class="itemWebsite" />
                </StackLayout>
            </ListView.itemTemplate>
        </ListView>
    </Page>
 
Ya sólo nos resta poner estilos, utilizando las clases itemName e itemWebsite que hemos utilizado en la vista. Para ello, creamos un nuevo fichero: main-page.css, donde meteremos los estilos de esta vista:
    StackLayout {
        padding: 20
    }
    .itemName {
        font-weight: bold
    }
    .itemWebsite {
        font-size: 11
    }
 
Y con esto queda completada esta pequeña aplicación para demostrar el uso de ListView.


Hello world Nativescript!

CLI de Nativescript

El CLI de Nativescript es una colección de herramientas en línea de comandos para construir y ejecutar aplicaciones Nativescript. Para comprender lo que estamos instalando, el CLI de Nativescript es un paquete npm instalado en nodejs.
Las aplicaciones Nativescript constan de:
  • Ficheros XML: el layout de la página (distribución de elementos) y los controles de UI
  • Ficheros Javascript: los eventos y la lógica de negocio
  • Ficheros CSS: el estilo de las páginas
El CLI coge los ficheros XML, JS, CSS y construye una aplicación que puede desplegarse en un simulador, en un emulador o en un dispositivo real. El CLI también se encarga de hacer el despliegue y ejecución de la aplicación.
El CLI de nativescript se lanza ejecutando el comando tns (que viene de Telerik NativeScript). El primer parámetro de tns es un comando que indica lo que tiene que hacer el CLI. La sintaxis de tns es:

    tns <command> [command parameters] [--options]

Comandos de tns:
  • doctor : chequea que la instalación de Nativescript está correcta
  • info : muestra información sobre Nativescript: versión de Nativescript instalada, versión de Android, iOS y core-modules (si estamos en el directorio de un proyecto). En todos los casos indica si existe una versión más moderna para actualizar.
  • proxy : muestra la configuración del proxy (si existe)
  • create : crea un nuevo proyecto Nativescript
  • platform add <platform> : configura el proyecto actual para una plataforma, ios o android
  • platform list : muestra todas las plataformas configuradas en el proyecto actual
  • platform remove <platform> : elimina una plataforma configurada del proyecto actual
  • platform update <platform> : actualiza una plataforma configurada en el proyecto actual
  • prepare <platform> : copia contenido especial desde el directorio app al directorio de la plataforma
  • build <platform> : construye el proyecto actual para una plataforma
  • deploy <platform> : despliega el proyecto actual a un dispositivo físico o emulador
  • run <platform> : ejecuta el proyecto actual en un dispositivo físico o emulador
  • debug <platform> : depura el proyecto actual en un dispositivo físico o emulador
  • install : instala todas las dependencias del proyecto especificadas en el fichero package.json del directorio del proyecto
  • appstore : muestra las aplicaciones registradas en appstore (sólo se puede ejecutar en OSX)
  • appstore upload : sube el proyecto actual al appstore (sólo se puede ejecutar en OSX)
  • device : muestra todos los dispositivos físicos o virtuales disponibles
  • device log : abre un stream de log para un dispositivo
  • update : actualiza la aplicación con las últimas versiones de core-modules y las plataformas instaladas
En resumen, el CLI nos permite:
  • Crear el esqueleto de la aplicación
  • Añadir plataformas (iOS y/o Android) a la aplicación
  • Construir la aplicación (.apk para Android, .ipa para iOS)
  • Desplegar la aplicación en un simulador, emulador o dispositivo
  • Ejecutar y depurar la aplicación en un emulador o simulador
  • Ejecutar la aplicación en un dispositivo conectado al ordenador

Esqueleto de la aplicación

El primer paso para tener una aplicación Nativescript es construir el esqueleto de la aplicación, que consta de una serie de directorios (con una estructura fija) y una serie de ficheros base.
No tenemos que crear ese esqueleto a mano, el CLI se encarga de crearlo a partir de unas plantillas que se descarga cuando creamos el proyecto. Estas plantillas son paquetes npm disponibles en http://www.npmjs.com (muchas de estas plantillas comienzan con tns-template).
Para lanzar el CLI de Nativescript, tenemos que abrir un 'Command Prompt' o un 'Powershell' en Windows, o bien, un 'terminal' en MacOSX.
Ir al directorio base donde tengamos todos los proyectos y ejecutar el comando:
 tns create HelloWorld
donde HelloWorld es el nombre de la aplicación.


Este comando crea un subdirectorio llamado HelloWorld en el directorio donde lo hemos ejecutado, y dentro de este subdirectorio, crea la siguiente estructura:
    /HelloWorld
        /app
        /hooks
        /node_modules
        /platforms
       package.json
Con este comando hemos creado un esqueleto de aplicación utilizando una plantilla por defecto, pero podríamos haber utilizado otra de las plantillas que existen en el repositorio npm. Para ello, tendríamos que haber añadido el parámetro: --template. Por ejemplo, para crear una aplicación con otro template (se pueden buscar templates en www.npmjs.com, pero lo habitual es partir del template por defecto):
    tns create EmptyApp --template tns-template-xxxxx

Plataformas

Nativescript soporta dos plataformas: iOS y Android. Cuando creamos el proyecto nuevo, el CLI no incluye ninguna plataforma al proyecto nuevo. Sin embargo, es necesario añadir al menos una plataforma a nuestro proyecto, para poder ejecutarlo en un simulador, emulador o dispositivo. Añadir una plataforma a nuestro proyecto se hace con el CLI.
La decisión de qué plataforma añadir es una cuestión de preferencias, pero si vamos a desarrollar en Windows, entonces sólo tenemos una alternativa: Android, ya que sólo podemos desarrollar para iOS en MacOSX. En cualquier caso, siempre podemos empezar con Windows/Android, y más adelante, en un Mac, añadir la plataforma iOS y compilar el proyecto para iOS. Así que este problema es secundario.
Para añadir plataformas a nuestro proyecto
    tns platform add android
    tns platform add ios
Estos comandos crean un nuevo subdirectorio (android o ios) debajo de HelloWorld/platforms, que contiene las librerías de runtime para cada plataforma.


Actualización de Nativescript

Nativescript se actualiza con frecuencia (cada mes o menos, tenemos actualizaciones). Para saber qué versión de Nativescript tenemos instalada:
    tns --version
Para actualizar Nativescript a la última versión:
    npm install -g nativescript
Una vez actualizada la versión de Nativescript, tenemos que actualizar los ficheros de runtime de cada plataforma y los core-modules de Nativescript:
    tns update
Este comando actualiza todo el proyecto. Si queremos actualizar por ejemplo una plataforma, haremos lo siguiente:
    tns remove <platform>
    tns add <platform>

Ejecución de la aplicación

Para ejecutar la aplicación:
    tns run android --emulator
    tns run ios --emulator
El CLI compila el código Nativescript (XML, JS y CSS) y lo enlaza con el runtime de la plataforma correspondiente, generando una aplicación.
El comando run construye la aplicación, genera el fichero APK ó IPA, lo despliega en el emulador y lo ejecuta. Este comando tarda un buen rato en poner en marcha la aplicación en el emulador (minutos en el caso de Android, dependiendo del equipo).



Flujo de trabajo

El comando run realiza todo el proceso, pero a veces es necesario ejecutar los pasos por separado.
Para construir la aplicación:
    tns build ios
    tns build android
El comando build enlaza el código de la aplicación con los módulos core y con el runtime de Nativescript y produce la aplicación nativa para iOS o Android.
El comando run, e incluso el comando build, tardan bastante tiempo en realizar su trabajo, y parece que desarrollar con Nativescript va a resultar un proceso engorroso, perdiendo gran parte del tiempo esperando a que la aplicación se construya y se lance en el emulador cada vez que hacemos un cambio en el código. Para resolver este problema, tenemos el comando livesync, que permite inyectar el código directamente en la aplicación que está corriendo en el emulador:
    tns livesync ios --emulator
    tns livesync android --emulator
La primera vez que se ejecuta el comando livesync, el CLI comprueba si la aplicación se ha construido y si está ejecutándose. Si no es así, el CLI la construye y la ejecuta. Si se vuelve a ejecutar el comando livesync de nuevo, el CLI busca los cambios en el código y sincroniza los cambios. Cada vez que hacemos un cambio en el código, tenemos que ejecutar livesync para que se sincronice.
Para evitar estar lanzando el comando livesync continuamente, existe una opción a este comando --watch para monitorizar continuamente los cambios en el código de la aplicación:
    tns livesync ios --emulator --watch
    tns livesync android --emulator --watch
A partir de la versión 3 de Nativescript, el comando run ya hace el trabajo equivalente a livesync y watch. Por tanto, simplemente tenemos que hacer run, no es necesario el comando livesync ni la opción --watch.

Aplicación vacía

El comando tns create crea una aplicación con cierta funcionalidad. No es mucho, pero sí tiene algunas cosas. Normalmente, lo que queremos es empezar nuestra aplicación desde cero, sin el código de ejemplo que mete el template por defecto. Podríamos utilizar el template tns-template-blank con la opción --template. Sin embargo, desde la versión 3, este template ha quedado obsoleto, y por tanto, no se recomienda usarlo.
Yo recomiendo vaciar el proyecto que nos crea por defecto tns create, y así partimos de una aplicación vacía. Para ello, podemos vaciar los siguientes ficheros:
  • app/app.css, se recomienda dejar la línea:
    @import 'nativescript-theme-core/css/core.light.css';
  • app/app.js
  • main-page.js
  • main-page.xml

Uso de Genymotion en Android

Una de las críticas habituales en el desarrollo para la plataforma Android es la lentitud en el arranque y recarga del emulador que viene con el SDK de Android. Si hemos seguido paso a paso lo que se indica en este artículo ya lo habremos podido comprobar: pueden pasar varios minutos desde que lanzamos la aplicación hasta que realmente se ejecuta en el emulador. Además, la interacción con el emulador también es bastante lenta y pesada.
Pero tenemos una alternativa: genymotion, un emulador Android mucho más ligero y rápido que el del SDK. Genymotion es gratuito para uso personal.
Para lanzar una aplicación Narivescript en genymotion, simplemente tenemos que lanzar un emulador genymotion y ejecutar el comando:
    tns run android --emulator
y la aplicación se lanzará en genymotion.

Instalación de Nativescript en MacOS

Homebrew

Abrir un terminal y ejecutar el siguiente comando:

    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Nodejs

En el terminal ejecutar:

    brew update
    brew install node@6

Dependencias para desarrollo iOS

Abrir el AppStore, buscar Xcode e instalarlo.
Entrar en https://developer.apple.com/downloads/index.action y descargar "Command line tools for Xcode"
En el terminal ejecutar:

    sudo gem install xcodeproj

Cocoapods

En el terminal ejecutar:

    sudo gem install cocoapods

Java JDK 8

Ir a http://www.oracle.com/technetwork/java/javase/downloads/index.html y descargar la última versión de JDK 8
Instalar el JDK descargado
Poner la variable JAVA_HOME:

    export JAVA_HOME=$(/usr/libexec/java_home)

Android SDK

En el terminal ejecutar:

    brew cask install android-sdk

Poner la variable ANDROID_HOME:

    export ANDROID_HOME=/usr/local/opt/android-sdk

Actualizar el Android SDK:

    android update sdk --filter tools, platform-tools, android-25, build-tools-25.0.2, extra-android-m2repository, extra-google-m2repository, extra-android-support --all --no-ui

Nativescript CLI

En el terminal ejecutar:

    npm i -g nativescript

Comprobar que se ha instalado correctamente:

    tns doctor
    tns --version