domingo, 4 de noviembre de 2012

Manejo de directorios en Objective-C


Un elemento clave en cualquier sistema que no sea muy pequeño, es el manejo de archivos. Por lo general, el manejo de archivos en el lenguaje C, en el cual se basa Objectibve-C, siempre es un poco complicado. Sin embargo, el framework Foundation, nos ayudará con varios métodos que nos harán la vida menos complicada, bueno, al menos el manejo de los archivos.

Las clases NSFileManager, NSFileHandle y NSData

NSFileManager - Esta clase puede ser utilizada para realizar operaciones básicas con archivos o carpetas como crear, mover, leer y escribir archivos y leer y modificar los atributos de los mismos. También cuenta con métodos para manejar los directorios, como leer su contenido, moverlos, borrarlos, etc.

  • NSFileHandle - Esta clase provee de operaciones de bajo nivel y de alto rendimiento, como búsqueda, lectura y escritura de arrchivos.
  • NSData - Esta clase maneja un buffer donde se puede leer y escribir los datos en un archivo.

Los nombre de las rutas de los archivos en Objective-C

Para las clases que se mencionan, los caminos de los archivos se manejan como en UNIX. Utilizamos la diagonal (/) para separar las carpetas. Si no inicia con la diagonal, entonces se considera a partir del directorio actual.

La carpeta inicial (o home) del cual puede el usuario iniciar, se maneja con una tilde (~). Su un archivo se escribe como  ~/miArchivo.m se hace referencia al archivo raiz del usuario. También se puede hacer la referencia a un directorio raíz de un usuario por medio de la tilde, por ejemplo ~pancho/demo.m, busca el directorio raíz del usuario "pancho".

Obteniendo la referencia por omisión con el objeto NSFileManager

La clase NSFileManager contiene un método llamado defaultManager podemos obtener la referencia a la carpeta donde se encuentra la aplicación:

NSFileManager *raiz;
raíz = [NSFileManager defaultManager];

A partir de este archivo, podemos utilizarlo de como apuntador para a partir de él, leer archivos y directorios.

Definir el directorio actual

El directorio de trabajo se puede obtener con el método currentDirectoryPath de la clase  NSFileManager. El método regresa el valor como una cadena NSString:

NSFileManager *raiz;
NSString *directorioActual;

raiz = [NSFileManager defaultManager];

directorioActual = [raiz currentDirectoryPath];

NSLog (@"El directorio actual es %@", directorioActual);

Cambio de directorio

Por medio del método changeCurrentDirectoryPath podemos cambiar de directorio de la aplicación. El nuevo destino del directorio es pasada como parámetro como un objeto NSString. Este método regresará un valor Booleano (YES/NO) para indicar si el cambio se efectuó en forma exitodsa o si existió un error:

NSFileManager *raiz;
NSString *dirActual;

raiz = [NSFileManager defaultManager];

dirActual = [raiz currentDirectoryPath];

NSLog (@"El directorio actual es %@", dirActual);

if ([raiz changeCurrentDirectoryPath: @"/temp/mydir"] == NO)
        NSLog (@"Error al cambiar de directorio.");

dirActual = [raiz currentDirectoryPath];

NSLog (@"El directorio actual es %@", dirActual);

Crear un nuevo directorio

Podemos crear un nuevo directorio por medio del método createDirectoryAtURLpasándole como un argumento a una instancia de la clase NSURL. Podemos pasarle diferentes atributos para el directorio:

NSFileManager *raiz;

raiz = [NSFileManager defaultManager];
NSURL *newDir = [NSURL fileURLWithPath:@"/tmp/mynewdir"];
[raiz createDirectoryAtURL: newDir withIntermediateDirectories:YES attributes: nil error:nil];

El método createDirectoryAtURL regresa un valor booleano indicando si la operación fue exitosa o no.

Borrar un directorio

Un directorio puede ser borrado del disco del sistema utilizando el mètodo removeItemAtPath, pasando como argumento el directorio que se desee eliminar:

An existing directory may be removed from the file system using the removeItemAtPath method, passing though the path of the directory to be removed as an argument:
 
NSFileManager *raiz;

raiz= [NSFileManager defaultManager];

[raiz removeItemAtPath: @"/tmp/mynewdir" handler: nil];

Renombrar o mover un directorio

Un directorio puede ser movido o renombreado usando el método moveItemAtURL. Este método toma como argumentos el origen y el destino por medio de objetos NSURL y es necesario que el objeto final NO EXISTA. Si el objeto destino ya existe, el étodo regresara un valor booleano negativo (NO):

NSFileManager *raiz;

raiz = [NSFileManager defaultManager];

NSURL *dirOrigen= [NSURL fileURLWithPath:@"/tmp/mynewdir"];
NSURL *dirNuevo= [NSURL fileURLWithPath:@"/tmp/mynewdir2"];

[raiz moveItemAtURL: dirOriegan toURL: dirNuevo error: nil];

Leer la lista de archivos del directorio

La lista de los archivos contenidos en un directorio se puede obtener por medio del método contentsOfDirectoryAtPath. Este método toma como argumento el camino del directorio que se desea leer como una cadena NSString y regresa un arreglo con los nombre de los archivos y subdirectorios contenidos:

NSFileManager *raiz;
NSString *dirActual;
NSArray *listaArchivos;
int num;
int i;

raiz= [NSFileManager defaultManager];

listaArchivos= [raiz contentsOfDirectoryAtPath: @"/tmp" error: nil];

num= [listaArchivos count];

for (i = 0; i < num; i++)
        NSLog (@"%@", [listaArchivos objectAtIndex: i]);

viernes, 2 de noviembre de 2012

Objective-C


Arreglos

Un arreglo (vector o matriz, depende del país) es un objeto que contiene colecciones de otros objetos. Los objetos Array en Objective-C se manejan con la clase NSArray

La clase NSArray contiene una serie de métodos específicamente diseñados para facilitar la creación y manipulación de los arreglos dentro de los programas de Objective-C. 

A diferencia de otros lenguajes de programación orientados a objetos (C # es un ejemplo), los objetos contenidos en un arreglo no todas tienen que ser del mismo tipo.

Arreglos mutables e inmutables


Los arreglos  en Objective-C vienen en dos sabores: inmutables y mutables. El contenido de un arreglo "inmutable" no puede cambiar en tiempo de ejecución. Los arreglos inmutables se crean como instancia de la clase NSArray. Los arreglo "mutables" se crean mediante la clase NSMutableArray (una subclase de NSArray) y puede ser modificada después de haber sido creado e inicializado.

Crear un arreglo

La clase NSArray contiene un método de clase llamado arrayWithObjects que se puede recurrir para crear un nuevo objeto Array y se inicializa con elementos. Por ejemplo:

NSArray *aColores;

aColores = [NSArray arrayWithObjects: @"Rojo", @"Verde", @"Azul", @"Amarillo", nil];

Es necesario añadir una entrada de tipo nil (en otros lenguajes es null, pero en Objective-C es nil) para que los métodos que se relacionan con los arreglos sepan donde termina este. Si omites la ultima entrada como nil, puede haber errores al momento de ejecutar tu aplicación.

Para crear un arreglo mutable que permitirá a los contenido de la matriz a modificar, tenemos que utilizar la clase NSMutableArray:

NSMutableArray *misColores;

misColores = [NSMutableArray arrayWithObjects: @"Rojo", @"Verde", @"Azul", @"Amarillo", nil];

Número de elementos de un arreglo


Para saber cuantos elementos tiene un arreglo, utilizamos el método count:

NSLog (@"Número de elementos en el arreglo = %lu", [misColores count]);

El índice de los arreglos, al igual que en la mayoría de los lenguaje que provienen de C, inicia en cero. Se puede acceder a los elementos de un arreglo, haciendo pasar la posición de índice a través de un argumento del método objectAtIndex

NSArray *misColores;
int i;
int lon;

misColores = [NSArray arrayWithObjects: @"Rojo", @"Verde", @"Azul", @"Amarillo", nil];

count = [misColores count];

for (i = 0; i < lon; i++)
        NSLog (@"Elemento %i = %@", i, [misColores objectAtIndex: i]);

Acceder a la información de un arreglo por medio de un ciclo for... in

NSArray *misColores;

misColores = [NSArray arrayWithObjects: @"Rojo", @"Verde", @"Azul", @"Amarillo", nil];


for (colores in misColores )
        NSLog (@"Elemento %@", color);

Añadir nuevos elementos a los arreglos mutables

Para añadir nuevos elementos a un arreglo mutable, lo realizaremos por medio del método addObject de la clase NSMutableArray. Por ejemplo:

[misColores addObject: @"Indigo"];
[misColores addObject: @"Violeta"];

Insertar elementos en un arreglo mutable por medio de un índice


Para insertar elementos en cualquier punto de un arreglo mutable, lo podemos efectuar por medio del método insertObject. Por ejemplo:

[misColores insertObject: @"Indigo" atIndex: 1];
[misColores insertObject: @"Violeta" atIndex: 3];

Borrar elementos de un arreglo

Objective_C nos proporciona muchos formas de  borrar elementos de un arreglo. Aquí se muestran las principales, pero puede ver la lista completa en la documentación de la librería Fundation.
Para borrar el elementos de un índice en específico se utiliza el método removeObjectAtIndex:
[misColores removeObjectAtIndex: 0];
Para borrar el primer elemento del arreglo utilice el método removeObject:
[misColores removeObject: @"Rojo"];

Para borrar un elemento por su contenido, utilice el método removeObjectIdenticalTo:
[misColores removeObjectIdenticalTo: @"Red"];

Para borrar todo el contenido de un arreglo, utilice el método removeAllObjects:
[misColores removeAllObjects];

Para borrar el último elemento de un arreglo, utilice el método  removeLastObject:
[misColores removeLastObject];

Ordenar un arreglo

Existen muchas formas de ordenar un arreglo. La más sencilla es por medio del método sortedArrayUsingSelector.

Por ejemplo:

NSMutableArray *misColore = [NSMutableArray arrayWithObjects: @"rojo", @"verde", @"azul", @"amarillo", nil];

NSArray *misColoresSorteados;

misColoresSorteados = [misColores sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
Como puede observarse, este método regresa otro objeto de tipo arreglo y utiliza el método localizedCaseInsensitiveCompare. Otros métodos que se pueden utilizar son NSOrderedAscendingNSOrderedSameNSOrderedDescending.

Objective-C


Diccionarios:



Los diccionario cumplen un propósito similar a los arreglos, almacenar información, excepto que cada objeto almacenado en el diccionario está asociada con una clave única (para ser más precisos, la clave es única para el objeto de diccionario particular). La clave única (key) puede ser de cualquier tipo de objeto, aunque para ser útil por lo general son cadenas.

En Objective-C los objetos de tipo diccionario se crean utilizando las clases NSDictionary y NSMutableDictionary. Los objetos NSDictionary ​​son inmutables (en otras palabras, una vez que se han creado e inicializado su contenido no se puede modificar).

Los diccionarios que se pueden modificar en tiempo de ejecución son instanciados de la clase NSMutableDictionary y puede ser modificada después de la creación y la inicialización.


Creación de objetos de diccionario


Un objeto diccionario "inmutable" (para seguir con la terminología de Apple) se puede crear de la siguiente manera:


NSDictionary *miDiccionario = [NSDictionary dictionary];


Un objeto diccionario que se pueda modificar en tiempo de ejecución, es decir, mutable (no mutante) se crea de la siguiente forma:


NSMutableDictionary *miDiccionario = [NSMutableDictionary dictionary];


Crear y poblar un objeto diccionario



Cada par de clave-valor contenido dentro de un diccionario se refiere a una entrada. Una vez que una relación entre una clave y un valor se ha establecido, la relación no se pueden modificar en tiempo de ejecución.

Las nuevas entradas se agregan a un diccionario utilizando el método de instancia setObject. Este método toma como argumentos un objeto y una tecla correspondiente:


NSMutableDictionary *misLibros = [NSMutableDictionary dictionary];

[misLibros setObject: @"La guerra y la paz"  forKey: @"100-432112"];
[misLibros setObject: @"Crimen y castigo" forKey:  @"200-532874"];
[misLibros setObject: @"Cien años de soledad" forKey:  @"202-546549"];
[misLibros setObject: @"La guerra de los mundos" forKey: @"104-109834"];




También es posible crear e inicializar un diccionario con un número de pares de clave-valor utilizando el método de la clase dictionaryWithObjectsAndKeys. Por ejemplo, una alternativa al código anterior es como sigue:


NSDictionary *misLibros = [NSDictionary dictionaryWithObjectsAndKeys: @"La guerra y la paz", @"100-432112", @"Crimen y castigo", @"200-532874", @"Cien años de soledad", @"202-546549", @"La guerra de los mundos", @"104-109834", nil];


Los diccionarios también se pueden poblar utilizando claves-valores contenidos en los arreglos utilizando el método arrayWithObjects:


NSArray *objectsArray = [NSArray arrayWithObjects: @"La guerra y la paz", @"Crimen y castigo", @"Cien años de soledad", @"La guerra de los mundos", nil];
NSArray *keysArray = [NSArray arrayWithObjects: @"100-432112", @"200-532874", @"202-546549", @"104-109834", nil];

NSDictionary *miLibros = [[NSDictionary alloc] initWithObjects: objectsArray  forKeys: keysArray];


Número de elementos en un diccionario


Para obtener el número de elementos de un diccionario, utilizamos el método count:


NSLog (@"Los libros en la lista son = %lu", [misLibros count]);


Acceder a los datos de un diccionario

Para acceder a los datos de un diccionario se hace referencia a la llave correspondiente a la entrada deseada mediante el método objectForKey. Por ejemplo:


NSLog ( @"100-432112 = %@", [misLibros objectForKey: @"100-432112"]);
NSLog ( @"200-532874 = %@", [misLibros objectForKey: @"200-532874"]);
NSLog ( @"202-546549 = %@", [misLibros objectForKey: @"202-546549"]);
NSLog ( @"104-109834 = %@", [misLibros objectForKey: @"104-109834"]);


Borrar un elemento del diccionario

Podemos borrar entradas específicas del diccionario mediante referencia a la llave como argumento al método removeObjectForKey. Por ejemplo, para eliminar la entrada de un libro, podemos escribir el siguiente código:


[misLibros removeObjectForKey: @"104-109834"];


Para eliminar todo el contenido de un diccionario utilizamos:


[misLibros removeAllObjects];

















martes, 1 de noviembre de 2011

Hacer menús del sistema con Adobe AIR

Las clases de “menú nativo” permiten acceder a las funciones del menú nativo del sistema operativo donde se ejecuta la aplicación.

Se pueden utilizar los objetos NativeMenu para:
  • menús de aplicación (disponibles en Mac OS X),
  • menús de ventana (disponibles en Windows y Linux),
  • menús contextuales y
  • menús emergentes. 
Aqui un ejemplo genérico de cómo hacer menús básicos en Windows y Mac:

package {
    import flash.display.NativeMenu;
    import flash.display.NativeMenuItem;
    import flash.display.NativeWindow;
    import flash.desktop.NativeApplication;
    import flash.display.Sprite;

    public class Menu01 extends Sprite {

        public function Menu01():void {
            var fileMenu:NativeMenuItem;
            var editMenu:NativeMenuItem;
           
            //Es Windows
            if (NativeWindow.supportsMenu) {
                stage.nativeWindow.menu = new NativeMenu();
                fileMenu=stage.nativeWindow.menu.addItem(new NativeMenuItem("Archivo"));
                editMenu=stage.nativeWindow.menu.addItem(new NativeMenuItem("Edición"));
            }
            //Es MAC
            if (NativeApplication.supportsMenu) {
                var mm:NativeMenu = new NativeMenu();
                NativeApplication.nativeApplication.menu = mm;
                fileMenu = NativeApplication.nativeApplication.menu.addItem(new NativeMenuItem("xxxxxxx"));
                editMenu = NativeApplication.nativeApplication.menu.addItem(new NativeMenuItem("ccccccc"));
            }
        }
    }
}

lunes, 10 de octubre de 2011

Leer los archivos los directorios del iPhone y Android con Adobe AIR

Parte fundamental de una aplicación para iPhone o Android será poder saber en que directorios se encuentra la aplicacion y los datos de la misma. Afortunadamente podemos leer y escribir información en los dispositivos móviles desde AIR. Contamos con las clases File y FileStream, así como el método resolvePath() y la propiedad nativePath. Un ejemplo de una clase que lea los directorios principales del dispositivos (en relación a la aplicación) sería el siguiente:

package com.app.dirFile {
    import flash.display.Sprite;
    import flash.filesystem.File;
   
    public class DirFile extends Sprite{

        public function DirFile() {
            init();
        }
       
        private function init(){
            salida_txt.text = "applicationDirectory: " + File.applicationDirectory.nativePath+ "\n\n";
            salida_txt.appendText("applicationStorageDirectory: " + File.applicationStorageDirectory.nativePath + "\n\n");
            salida_txt.appendText("userDirectory: " + File.userDirectory.nativePath + "\n\n");
            salida_txt.appendText("documentsDirectory: " + File.documentsDirectory.nativePath+ "\n\n");
            salida_txt.appendText("desktopDirectory: " + File.desktopDirectory.nativePath+ "\n\n");
            salida_txt.appendText("applicationDirectory URL: " + File.applicationDirectory.url+"\n\n");
            salida_txt.appendText("desktopDirectory URL: " + File.desktopDirectory.url +"\n\n");           
        }
    }
}
iPhone no soporta la opcíon de desktopDirectory ni applicationDirectory, a comparación de Android que si las soporta.

jueves, 6 de octubre de 2011

Marcar una llamada telefónica desde tu iPhone con ActionScript 3.0

Aunque usted no lo crea, el iPhone también sirve para hacer llamadas telefónicas. Solo necesitamos invocar el protocolo "tel:" más el número que deseamos marcar. Se levantará el servicio telefónico del equipo y se realizará la llamada como si la hubiera marcado desde el teléfono. El código básico para realizar una llamada es el siguiente:

package  {
    import flash.display.MovieClip;
    import flash.net.URLRequest;
    import flash.net.navigateToURL;
    import flash.events.MouseEvent;
   
   
    public class Telefono extends MovieClip {
       
       
        public function Telefono() {
            init()
        }
       
        private function init(){
            marcar_btn.addEventListener(MouseEvent.CLICK, onMarcar);
        }
       
        private function onMarcar(e:MouseEvent):void {
            var num:String = "tel:"+telefono_txt.text;
            ejecutaComando(num);
        }

        private function ejecutaComando(comando:String):void{
            var req:URLRequest = new URLRequest(comando);
            try{
                navigateToURL(req);
            }
            catch(e:Error){
                trace("Ocurrio un error");
            }
        }
    }
   
}
En el archivo fla necesitará una caja de texto de entrada (del tipo que desee) y un botón con el nombre de instancia marcar_btn

martes, 4 de octubre de 2011

Detectar la geolocalizacion en iPhone con ActionScript 3.0

Por medio de dos clases podemos recibir la psoción geográfica del iPhone: Geolocation y GeolocationEvent.

La clase GeolocationEvent.nos proporciona los datos de geolocalización. Estos datos son los siguientes:


Propiedad isSupported:Boolean indica si el dispositivo soporta la geolocalización

Propiedad muted:Boolean Indica si el usuario autoriza el uso del geolocalizador en su dispositivo

Método setRequestedUpdateInterval(interval) Establece el intervalo en milisegundos de la frecuencia de monitoreo del geolocalizador

Evento StatusEvent.Indica si el usuario modificó el acceso al geolocalizador

Evento GeolocationEvent. Actualiza cuando el sensor del dispositivo actualiza la localización

La estructura clásica previa al uso del geolocalizador es la siguiente:

if (Geolocation.isSupported)
{
     var geo:Geolocation = new Geolocation();
     geo.setRequestedUpdateInterval(200);
     geo.addEventListener(GeolocationEvent.UPDATE, onGeo);
     geo.addEventListener(StatusEvent.STATUS, onGeoStatus);
}
else
{
    trace("Lo siento, no posees GPS");
}

Dentro del objeto de evento del manejador GeolocationEvent.UPDATE tendremos los siguientes parámetros:

altitude La altitud en metros.
heading La dirección del movimiento en grados (0–359) donde el norte es cero.
horizontalAccuracy Exactitud horizontal en metros
latitude Latitud en gradosentre  90 y –90. Si es positiva es norte y negativa el sur.
longitude Longitud entre 180 y –180.Positivo es este y negativo oeste.
speed Velocidad de movimiento en metros por segundo
timestamp Tiempo de actualización del sensor en milisegundos
verticalAccuracy Exactitud vertical en metros.