Abril 23, 2008

Testing: Hopefully not nobody

Que yo recuerde, las versiones anteriores de XCode no incluían en la plantilla de los proyectos ningún archivo de créditos. Según parece, ahora ya sí...

hopefully.png

"Hopefully not nobody". Tiene su chispa.

Abril 01, 2008

FND 1.2

Se acaba de liberar una nueva versión de FND (film is not dead), la aplicación para Mac OS X que viene en ayuda de aquellos que amamos la fotografía analógica y que disfrutamos revelando película con nuestras propias manos.

FND es una tabla de tiempos y reveladores, que permite tener organizada y clasificada tu experiencia con las diferentes combinaciones de película y revelador. Además, FND es un reloj de revelado, que puede funcionar en modo fullscreen, y que es controlable a través del Apple Remote.

La aplicación es sólo para Leopard, tiene un período de prueba de 30 días, y su precio es de 12.95 dólares.

Esta nueva versión incluye, entre varias mejoras de usabilidad, la localización en castellano.

Marzo 19, 2008

Uso de Core Animation para modificar el contenido de una vista

Uno de los frameworks que han hecho su debut con Leopard ha sido Core Animation.

Según Apple, Core Animation es un framework para renderizado gráfico, proyección y animación. Lo que, traducido, quiere decir, que es un framework que facilita enormemente la animación de elementos de interfaz.

Por ejemplo, es muy sencillo cambiar en tiempo de ejecución el contenido de una vista, sustituyéndolo por otra vista completamente distinta, presentando el cambio con una animación discreta, pero efectiva para reforzar el feedback que recibe el usuario del proceso.

En este ejemplo vamos a partir de este primer estado:

swap_final_1.png

Para llegar a este otro:

swap_final_2.png

Como puede verse, en este caso el cambio no es muy grande, se pasa de un slider a un desplegable, no obstante, la transición se hará utilizando la animación por defecto del framework (dissolve).

Construir el interfaz de la aplicación es sencillo. En la ventana principal de la misma, voy a colocar un botón, que será el que lance la animación, y una instancia de NSView, cuyo contenido iré modificando en tiempo de ejecución. Éste sería el aspecto de mi ventana:

swap_ventana.png

Además, construyo dos instancias más de NSView:

swap_view1.png

swap_view2.png

Como se puede ver, el ancho de las dos vistas es diferente.

Construyo también el esqueleto del controlador de la aplicación. Tendré tres outlets, uno a cada uno de las tres vistas (la de la ventana principal, y las dos vistas independientes). Además, tendré un action para el botón de "swap" y un booleano que me indicará si la vista que se está mostrando en cada instante es la primera o la segunda:

#import


@interface ViewSwapController : NSObject
{
IBOutlet NSView *containerView;
IBOutlet NSView *firstView;
IBOutlet NSView *secondView;

BOOL showFirst;
}

-(IBAction) swapView: (id) sender;
@end

Tras crear la instancia de NSObject en Interface Builder y asignarle como clase mi controlador, la estructura del nib sería como la siguiente:

swap_nib.png

Quiero que mi controlador haga lo siguiente: al arrancar la aplicación, insertará dentro de la vista de la ventana principal la primera de las dos vistas independientes que he creado, y cuando se haga clic en el botón de "swap" se cambiará esa vista por la segunda.

Por tanto, el método awakeFromNib será:

-(void) awakeFromNib
{
showFirst = NO;

[ containerView setWantsLayer: YES ];

[ [ containerView animator ] addSubview: firstView ];
}

Simplemente, preparo la vista de la ventana principal para que sea animable, y le añado como subvista la primera de mis vistas personalizadas.

Al hacer clic en el botón:

-(IBAction) swapView: (id) sender
{
NSRect containerFrame = [ containerView frame ];
NSRect firstViewFrame;
NSNumber *newCoord;
NSView *tempFirst;
NSView *tempSecond;

if( showFirst )
{
tempFirst = secondView;
tempSecond = firstView;

showFirst = NO;
}
else
{
tempFirst = firstView;
tempSecond = secondView;

showFirst = YES;
}

[ [ containerView animator ] replaceSubview: tempFirst with: tempSecond ];

firstViewFrame = [ tempSecond frame ];

newCoord = [ NSNumber numberWithFloat: containerFrame.size.width /2 - firstViewFrame.size.width/2 ];

[ tempSecond setFrameOrigin: NSMakePoint( [ newCoord intValue ] , 0 ) ];

}


En primer lugar, calculo el ancho de la vista contenedor, y de la vista que quiero colocar dentro de la misma, para luego poder centrarla, y posteriormente reemplazo la vista que esté dentro del contenedor por la que corresponda.

Lo importante, lo que hace que la transición entre las dos vistas sea animada, es que no ataco directamente la vista contenedor para modificar su contenido, sino que utilizo el decorator que crea CoreAnimation (que se llama animator) para que, de esa forma, cualquier modificación de las propiedades de esa vista se muestre de forma animada.

El proyecto puede descargarse del repositorio público de subversion:

svn co http://svn.liadorasoft.com/viewswap ViewSwap

Enlaces relacionados:
Un clon de Photo Booth en 32 minutos
Extensión por delegación
Bindings, NSArrayController y Value Transformers

Marzo 07, 2008

iPhone SDK

Ya está, ya hay un SDK para el iPhone/iPod Touch. Por fin se van a poder desarrollar y distribuir aplicaciones de forma "oficial", soportada por Apple y sin necesidad de hacer nada estraño con el aparato.

Desde mi punto de vista, como parte interesada, como usuario y como desarrollador, hay varias cosas que me han llamado la atención.

¿Documentación?
En primer lugar, la mayor sorpresa ha sido lo bien documentada que está la plataforma, sobre todo teniendo en cuenta que Apple tiende a producir una documentación más bien opaca, que es poco más que una enumeración de los interfaces de sus APIs.

Esta vez no sólo se han publicado documentos "en papel" sino una serie de vídeos en ADC on iTunes que sobrepasan con creces, en calidad de contenidos, lo que había disponible hasta ahora (exceptuando las sesiones de la WWDC). Lo que me lleva a pensar dos cosas más.

No es el iPhone ni el iPod, es lo que está por venir
La sensación, al menos la que yo tengo, es que lo que se documenta no es sólo el SDK para iPhone e iPod Touch, sino que lo se documenta es la plataforma de Apple para dispositivos con pantalla táctil.

Es decir, que la sensación que a mí me ha quedado es la de que lo que se abre hoy no es la puerta al desarrollo para un cacharro, sino para muchos, que compartirán ciertos frameworks. Conociendo la arquitectura de los frameworks de Apple no es nada descabellado pensar que este SDK mañana sirva para desarrollar aplicaciones para el sistema de control de un coche, o para un tablet, o para lo que sea que se pueda manejar con los dedos.

Y eso está muy bien.

Cuota de mercado
La otra conclusión es que esta plataforma (la llamémosla móvil) no tiene las limitaciones en cuanto a cuota de mercado que tiene un Mac. Apple lo sabe, y le da la importancia pertinente al SDK. D e hecho, se ha dividido el Developer Connection en dos partes jerárquicamente igual de importantes: el iPhone Developer Program, y el Mac Developer Program.

Sinceramente, llama la atención ver el esfuerzo que ha puesto Apple en facilitar a los desarrolladores la adaptación a esta plataforma.

Eso es, obviamente, bueno. Cuantos más sean (o seamos) desarrollando aplicaciones, mejores aplicaciones habrá. Lo que lleva al siguiente punto.

Modelo de distribución
Sinceramente, no me parece mal que las aplicaciones se distribuyan vía iTunes. No me tengo que preocupar de montar la web del producto, ni un sistema de cobro on-line, y más importante aún, mi aplicación está disponible para mis futuros usuarios desde el mismo dispositivo en el que se va a utilizar. Lo que va en la línea de actuación de Apple, por cierto, que no es otra que poner lo más fácil posible a la gente que pueda comprar. Y si yo quiero vender, y Apple lo pone fácil para comprar, la cosa me gusta.

Peeeeeeeeero, y siempre hay un pero, lo que no me gusta es que Apple tenga que aprobar la entrada de la aplicación en la tienda. Entiendo que ellos intentan proteger, por un lado, al proveedor de servicios móviles, y por otro, su propia reputación, pero eso tiene dos cosas muy malas, relacionadas: Apple puede decidir cerrar el paso a una aplicación porque le guste la idea, y puede decidir desarrollar una apliación similar por sí misma.

Lo de los 99$ por poder firmar aplicaciones y distribuirlas en la tienda de iTunes no me parece tan grave. Total, es lo que me iba a costar el hosting. Lo mismo pasa con el 30% de comisión que se queda Steve. Es alta, es cierto, pero tampoco es tan grave.

Lo que sí que toca las canicas es el empeño que tiene Apple en poner una línea entre usuarios/desarrolladores de USA y del resto del mundo. Que, digo yo, que algún día se nos va a acabar la paciencia.

El flujo de trabajo
Lo primero que me ha llamado la atención del SDK es que el emulador funciona muy bien. Lo segundo es que, por favor, hace falta un Interface Builder específico, que para hacer layouts a mano ya existe Java.

Poco más se puede decir, la verdad. Las herramientas son las de siempre, el lenguaje es el de siempre (aunque, ojo, sin recolector de basura, así que hay que volver al hold me - use me - release me) y todo es como siempre.

Sólo que, esta vez, con muchísima más expectación que otras veces.

Ahora, ya, sólo queda empaparse por completo de la documentación, y comprobar si, por favor, finalmente ha entrado en el SDK público el acceso a los SyncServices...

Febrero 10, 2008

FND 1.1.1

Release de mantenimiento de FND (film is not dead), la aplicación para Mac OS X que viene en ayuda de aquellos que amamos la fotografía analógica y que disfrutamos revelando película con nuestras propias manos.

FND es una tabla de tiempos y reveladores, que permite tener organizada y clasificada tu experiencia con las diferentes combinaciones de película y revelador. Además, FND es un reloj de revelado, que puede funcionar en modo fullscreen, y que es controlable a través del Apple Remote.

La aplicación es sólo para Leopard, tiene un período de prueba de 30 días, y su precio es de 12.95 dólares.

Enero 31, 2008

Entresijos. Haciendo la web. El nuevo proyecto de Design-Nation

Durante los próximos días, tomará cuerpo "Entresijos. Haciendo la web", el nuevo y por ahora último proyecto que sale de la cocina de ideas del emporio Design-Nation.

¿Qué es "Entresijos" ?

Se trata de un podcast, en formato entrevista y mesa redonda, de una duración no superior a media hora por episodio, por el que queremos que pase la mayor cantidad de profesionales que, de una u otra manera, desarrollen su actividad en relación con internet.

No es un podcast de y para programadores, sino que queremos que sirva como plataforma en la que todos los perfiles implicados en la construcción de internet (programadores, técnicos de sistemas, diseñadores, expertos en HCI, formadores, jefes de proyecto, bloggers, editores de webs de noticias, etc) y también aquellos que desde el otro lado de la barrera utilizan lo que los primeros construyen, puedan explicar en qué consiste su trabajo, cuáles son los retos con los que se enfrentan día a día, y cuál es la dirección que creen que debe tomar el futuro cercano, tanto de su parcela profesional como del negocio en general.

En el grupo de personas con el que estamos contactando hay programadores cliente y programadores servidor, técnicos de sistemas, diseñadores, animadores, expertos en e-learning, expertos en usabilidad,  directores de agencias de publicidad, o project managers.

Aprovechamos desde ya, para agradecer la colaboración de quienes en el último mes y medio nos han confirmado su deseo de participar. Y confiamos en que haya más gente colaborando a futuro.

Esperamos que os guste.

Enero 23, 2008

Bindings, NSArrayController y Value Transformers

Parece el título de una mala película de acción, de esas que estiran hasta más allá de lo razonable y lo creíble la trama de un comic, pero es aún peor, porque es el título de la última aventura de El Gran Dragón.

Y es que Bruce le ha ordenado que construya una prueba de concepto, una aplicación funcional, pero no muy compleja, que presente en un listado unos cuantos iconos. En concreto, los que corresponden con NSComputer, NSFolderBurnable y NSFolderSmart, que como El Gran Dragón bien sabe, Apple ha expuesto para su uso a partir de Leopard.

El Gran Dragón sabe que su Gran Maestro gusta de las aplicaciones sencillas y elegantes, de tener un núcleo funcional desde etapas muy tempranas sobre el que ir realizando los refinamientos necesarios y, por eso, su primera idea llega rápida como el ataque de una serpiente: "voy a construir una aplicación con un controlador, que tenga agregado un array mutable, array que controlaré con una instancia de NSArrayController, de forma que, por bindings, asigne el contenido del listado que constituye el interfaz de la aplicación a partir del contenido de ese array".

No está mal. Una solución sencilla, elegante, que utiliza en su beneficio muchos de los frameworks y metodologías de desarrollo para Mac OS X y cuya arquitectura sigue las líneas maestras de lo que se consideran "buenas prácticas".

Por tanto, El Gran Dragón comienza por crear el proyecto, como siempre, y por crear el controlador de la aplicación, una clase llamada AppController, que agregará un array mutable. La cabecera de esa clase sería por tanto:

#import


@interface AppController : NSObject
{
NSMutableArray *iconsCollection;
}

@property(copy, readwrite) NSMutableArray *iconsCollection;

@end

El interfaz de la aplicación tampoco tiene mucha complicación. Basta con crear en Interface Builder una instancia de NSObject y asignarle su tipo al controlador de la aplicación, y construir un interfaz con un NSTableView con una única columna, sobre la que El Gran Dragón arrastra una instancia de NSImageCell, para de esa forma poder presentar imágenes en la tabla.

interfaz_transformer.png

Bien, se dice a sí mismo el Gran Dragón. "Como tengo un controlador de la aplicación responsable de crear un array mutable, si consigo colocar en ese array mutable las imágenes que quiero presentar en el interfaz, sólo tendría que asignar el binding correspondiente en Interface Builder para que mi aplicación presentara las imágenes".

Como ya era tarde, El Gran Dragón se marchó a la cama sonriente, pensando que había encontrado la solución a su problema. Sin embargo, a altas horas de la madrugada, su maestro se le apareció en sueños: "Gran Dragón, ¿acaso has olvidado todo lo que te he enseñado? De verdad crees que es necesario crear esas imágenes? ¿Y si quisieras serializar el modelo a disco? No entiendes que no es necesario crear tantas instancias de NSImage, sobe todo si las puedes crear en tiempo de ejecución? ¿No te parece?"

El Gran Dragón despertó sudoroso, pero con una mirada de gran determinación. "¡Es cierto! Puedo crear las instancias de NSImage al vuelo, lanzándole un mensaje como éste!":

[ NSImage imageNamed: @"NSComputer" ];

Por tanto, sólo necesitaría guardar en el modelo las cadenas de texto con los nombres de las imágenes a crear. Pero, ¿cómo hago para convertir esa cadena de texto en una instancia de NSImage, que es a lo que necesito bindar la columna de mi tabla?

Pues utilizando un Value Transformer. Un Value Transformer es una clase que ejerce como mediador en el mecanismo de bindings. Si esa clase existe, antes de pasarle al interfaz lo que debe dibujar, se le pasa al mediador el valor extraído del modelo, y es el mediador el que, tras hacer lo que deba con ese valor, quien le termina por dar al interfaz lo que éste necesita.

En este caso, el interfaz (la columna de la tabla) necesita instancias de NSImage, mientras que lo que El Gran Dragón va a guardar en el modelo con cadenas de texto. Por tanto, el Value Transformer será el que cree las instancias de NSImage necesarias a partir de ese valor de texto.

Lo primero es crear la entidad básica del modelo. El Gran Dragón ha decidido, en un alarde de originalidad, llamarla AppEntity:

#import


@interface AppEntity : NSObject
{
NSString *iconName;
}
@property(copy, readwrite) NSString *iconName;
@end


La implementación:

#import "AppEntity.h"


@implementation AppEntity
@synthesize iconName;
@end


Ahora, El Gran Dragón escribe la implementación de su controlador para que, al crearse, éste cree las tres instancias de esa entidad que El Gran Maestro le ha pedido. Por tanto, AppController.m será:

#import "AppController.h"
#import "AppEntity.h"
#import "DNIconValueTransformer.h"


@implementation AppController
@synthesize iconsCollection;
-(id) init
{
self = [ super init ];

NSValueTransformer *iconTransformer = [ [ DNIconValueTransformer alloc ] init ];
[ NSValueTransformer setValueTransformer: iconTransformer forName:@"IconImageTransformer"];

iconsCollection = [ [ NSMutableArray alloc ] init ];

AppEntity *entityOne = [ [ AppEntity alloc ] init ];
entityOne.iconName = @"NSComputer";
[ iconsCollection addObject: entityOne ];

AppEntity *entityTwo = [ [ AppEntity alloc ] init ];
entityTwo.iconName = @"NSFolderBurnable";
[ iconsCollection addObject: entityTwo ];

AppEntity *entityThree = [ [ AppEntity alloc ] init ];
entityThree.iconName = @"NSFolderSmart";
[ iconsCollection addObject: entityThree ];

return self;
}
@end

Como puede verse, al inicializarse el controlador también se registra el Value Transformer, asignándole como nombre IconImageTransformer.

El siguiente paso de El Gran Dragón, por tanto, es escribir esa clase, que tendrá la siguiente cabecera:

#import


@interface DNIconValueTransformer : NSValueTransformer
{

}

@end

Como se puede ver, el único misterio que tiene es que extiende de NSValueTransformer.

La implementación tiene un poco más de miga:

#import "DNIconValueTransformer.h"


@implementation DNIconValueTransformer

+ (Class)transformedValueClass
{
return [ NSImage class ];
}

+ (BOOL)allowsReverseTransformation
{
return YES;
}

- ( id ) transformedValue:( id )value
{
NSLog( @"transformador %@", value );

if( value != nil )
{
return [ NSImage imageNamed: value ];
}
else
{
NSLog( @"pasa por el transformador" );
return nil;
}
}

@end

Aunque tampoco es muy complicada. El método transformedValueClass devuelve el nombre del tipo de retorno del método que va a realizar la transformación: transformedValue. En este caso, lo que se va a crear son imágenes, por tanto devuelve NSImage.

El método de transformación en sí tampoco es muy complejo. Simplemente se crea la instancia de NSImage a partir del nombre de la imagen que se le pasa al transformador desde el modelo.

Ahora, de vuelta en Interface Builder, hay que crear una instancia de NSArrayController, y encargarla manejar la colección de iconos:

controlador_Array.png

El último paso es asignar el binding de la columna de la tabla.

table_column_bindings.png

Como se puede ver, se binda al valor de la propiedad iconName de la entidad del modelo, pero utilizando la transformación que El Gran Dragón registró previamente como IconImageTransformer.

De esa forma, el resultado final es el que se pretendía conseguir:

icons_final.png

Y se ha conseguido con un modelo ligero, sin gran consumo de memoria ni de recursos del sistema, que puede ser serializado fácilmente.

Es un paso más para El Gran Dragón en el largo camino de la sabiduría.

El proyecto completo puede descargarse de este enlace

Emporio dNation

Powered by
Movable Type 3.2