Desarrollo de una aplicaciÛn para Mac OSX: dado
Hay dos cosas que nos gustan particularmente en design-nation: los dados, y las aplicaciones para Mac OSX. AsÌ que hemos desarrollado una pequeÒa aplicaciÛn ( lo has adivinado, un dado ) con la finalidad de enseÒar aunque sea por encima cÛmo es el proceso de desarrollo en el Mac. Lo haremos utilizando XCode y escribiendo cÛdigo en Objective-C
En todo caso, como casi cualquier otro tutorial sobre XCode que se pueda escribir, el nuestro queda oscurecido por el que hay en el Apple Developer Connection. LÈelo!
Pero antes, echa un vistazo al resultado final:
Antes de empezar a picar cÛdigo como locos, parÈmonos a pensar cÛmo vamos a implementar la aplicaciÛn. Generaremos un n˙mero entre 1 y 6, y despuÈs cargaremos un png que contendr· la cara del dado que corresponda a ese n˙mero y lo mostraremos en el interfaz.
Siempre es bueno desarrollar cualquier aplicaciÛn siguiendo el paradigma MVC, pero en este caso, veremos cÛmo XCode y el Interface Builder hacen esa implementaciÛn f·cil e intuitiva.

Bien, empecemos. en primer lugar, abre XCode ( si no lo encuentras, est· escondido en la carpeta /Developer/Applications ). DespuÈs selecciona File-> New Project, y cuando te pregunte, elige "Cocoa Application". Entonces, escribe el nombre y elige la carpeta en disco donde crear los archivos del proyecto. Tras hacer eso, se abrir· la ventana del proyecto ( "Project Window" )
No nos vamos a meter a explicar quÈ son todos los archivos y carpetas que se han creado. Adem·s, hay varios tutoriales ( incluso la documentaciÛn de XCode ) que lo explican. Por tanto, pasemos directamente a trabajar en el interface.
øPero cÛmo?. Nuestra aplicaciÛn estar· basada en el MVC. eso significa que el interfaz de usuario ( la vista ) ser· totalmente independiente de la lÛgica de la aplicaciÛn ( el modelo ). Y XCode y el Interface Builder har·n un excelente papel a la hora de facilitar esa implementaciÛn.
Para empezar, por tanto, haz doble click en el archivo MainMenu.nib. De ese modo se abrir· el Interface Builder.
El Interface Builder es una herramienta visual que permite, como su nombre indica, construir el interfaz de la aplicaciÛn. Pero no sÛlo eso, sino que nos asegura que, si seguimos las guÌas que nos proporciona, cumpliremos con las User Interface Guidelines de Apple. Veamos cÛmo.

En primer lugar, adapta el tamaÒo de la ventana del programa a tus necesidades. Para hacerlo, puedes arrastrar la esquina inferior derecha, o abrir el Inspector, seleccionar Size, e introducir los valores a mano. En nuestro ejemplo, hemos seleccionado un ancho de 240 y un alto de 280. En la secciÛn de Attributes se pueden cambiar el nombre de la ventana, fondo, y otras propiedades.
Ahora, aÒade los elementos de interfaz que vamos a necesitar. Akade un NSImageView ( de la pestaÒa Cocoa-Containers ) y un Button ( de la pestaÒa Cocoa-controls ).

Arrastra la instancia del NSImageView, y suÈltala sobre la ventana. Mientras la arrastras, ver·s cÛmo el Interface Builder dibuja unas lÌneas que ayudan a posicionarlo. Seguir esas guÌas asegurar· que se est·n cumpliendo las User Interface Guidelines de Apple.
A continuaciÛn aÒade el botÛn al interfaz. Arrastra el botÛn de la paleta a la ventana de la aplicaciÛn ( recuerda, deja que las guÌas te guÌen ), y tras soltarlo, mientras a˙n est· seleccionado, presiona Option y muÈvelo usando los cursores. Ver·s cÛmo el Interface Builder muestra la distancia entre el botÛn y el elemento del interfaz que estÈ debajo del cursor del ratÛn. Por tanto, coloca el cursor sobre el NSImage View, y centra el botÛn respecto a Èl.
Ahora, asigna el texto del botÛn, haciendo doble click sobre Èl, y tras hacerlo, vete a la secciÛn de Attributes del Info panel, y selecciona el atajo de teclado para el botÛn ( en este caso, Enter ).
Para asegurarnos que el botÛn tendr· el foco cuando se arranque la aplicaciÛn, setearemos el initialFirstresponder. Para ello, hay que arrastrar ( con Control presionado ) una lÌnea de conexiÛn desde la instancia de window en la ventana MainMenu.nib, hasta el botÛn. Una vez hecho, hay que seleccionar en el Info panel initialFirstResponder, y hacer click en "Connect"
El interfaz ya casi est· terminado. SÛlo falta conectarlo con el modelo de la aplicaciÛn, lo que haremos a travÈs del controlador.
Pero antes de hacerlo, vamos a ver r·pidamente quÈ son los "outlets" y los "actions". Los outlets son variables de instancia de una clase que apuntan a otro objeto. Dicho de otra forma, un outlet es una referencia que un objeto mantiene a otro objeto distinto. Sin embargo, una acciÛn ( action ) es similar a un mÈtodo p˙clico de una clase. Mejor dicho, es la forma de encapsular el envÌo de un mensaje a un target determinado.
En todo caso, el Interface Builder facilita el proceso de crear outlets y actions

En primer lugar, tendremos que crear la clase que haga el papel de controlador. Para ello, en el panel Classes de la ventana MainMenu.nib, hay que hacer click, en el panel m·s a la izquierda, en NSObject. A continuaciÛn, debe presionarse Return. Entonces, hay que nombrar la nueva clase como DiceController. De ese modo, hemos creado una subclase de NSObject ( la clase base de toda la jerarquÌa ).

Ahora, definiremos los outlets para esa clase. DiceController es el controlador, por lo que tendr· un outlet al NSImageView del interfaz, y otro al modelo ( una clase que no hemos creado a˙n ). Por tanto, selecciona "DiceController", y en el Info Panel, selecciona Attributes. A continuaciÛn aseg˙rate que el panel Outlets est· seleccionado, y haz click en add. Llama el outlet imageView, y asÌgnalo el tipo NSImageView ( un poco de tipado no viene mal ).
Ahora aÒade otro outlet, que ser· el que apunta al modelo, y ll·malo dice.
Para crear la acciÛn que ser· ejecutada cuando se haga click en el botÛn, selecciona el panel de acciones ( en el Info Panel ), haz click en add y da a la acciÛn el siguiente nombre: roll.
Ya hemos descrito el controlador, incluyendo sus outlets y actions. Ahora es el momento de conectar este controlador con el interfaz. Para hacerlo, en primer lugar habr· que crear una instancia de la clase DiceController, seleccionando la clae en la ventana MainMenu.nib, y a continuaciÛn seleccionando Instantiate en el men˙ Classes. La nueva instancia aparecer· en el panel de instancias. Para conectarla con el interfaz, Control-Drag una lÌnea desde la instancia de la clase hasta el NSIMageView del interfaz. Cuando sueltes el botÛn, selecciona el outlet que estar· asignado a esa conexiÛn ( en nuestro ejemplo inageView ), y haz click en connect. Para conectar el botÛn en la vista con el controlador, Control-Drag desde el botÛn hasta la instancia de DiceController. Al soltar el botÛn, selecciona roll en la columna de las acciones y haz click en connect.

Para crear el modelo ( Dice ), define una nueva subclase de NSObject y crea una instancia de esa clase. A continuaciÛn, crea una conexiÛn de outlet entre DiceController y Dice. °Y ya est· todo conectado!
Una vez que hemos concluido con el trabajo en el interfaz, es el momento de que XCode genere el cÛdigo necesario. Para ello, selecciona una de las dos clases en la ventana MainMenu.nib, y selecciona Create classes en el men˙ Classes. A continuaciÛn haz lo mismo con la otra clase.
Mira el cÛdigo generado. Ver·s que hay un mÈtodo sin implementar en DiceController.m. ImplementÈmoslo.
@implementation DiceController
- (IBAction)roll:(id)sender
{
[ imageView setImage: [ dice image ] ];
}
@end
El cÛdigo es muy sencillo. Simplemente, setearemos en contenido de imageView ( que es uno de los outlets de esta clase ), con una imagen que obtendremos del modelo ( el otro outlet ).
Por tanto, ahora concluiremos la implementaciÛn del modelo. Esta clase tendr· un mÈtodo que generar· un n˙mero aleatorio entre 1 y 6, y cargar·, dependiendo de ese valor, un png diferente de disco. DespuÈs le pasar· la imagen cargada al controlador.
Por tanto, el constructor del modelo ser·:
-( id ) init
{
self = [ super init ];
image = nil;
srand( time( NULL ) );
return self;
}
Para evitar agujeros de memoria, se liberar·n los recursos al liberar la clase:
- ( void ) dealloc
{
[ image release ];
[ super dealloc ];
}
Los png estar·n en el bundle de la aplicaciÛn. Por tanto, lo primero ser· obtener una referencia a ese bundle:
-( NSImage* ) image
{
NSBundle *bundle = [ NSBundle bundleForClass: [ self class ] ];
NSString *imgName = [ bundle pathForResource: [ self generateImageName ] ofType: @"png" ];
image = [ [ NSImage alloc ]
initWithContentsOfFile: imgName ];
return image;
}
El cÛdigo completo de Dice.m ser·, finalmente:
#import "Dice.h"
@implementation Dice
-( id ) init
{
self = [ super init ];
image = nil;
srand( time( NULL ) );
return self;
}
- ( void ) dealloc
{
[ image release ];
[ super dealloc ];
}
-( NSString* ) generateImageName
{
int random = ( rand( ) % 6+ 1 );
return [ NSString stringWithFormat: @"%i", random ];
}
-( NSImage* ) image
{
NSBundle *bundle = [ NSBundle bundleForClass: [ self class ] ];
NSString *imgName = [ bundle pathForResource: [ self generateImageName ] ofType: @"png" ];
image = [ [ NSImage alloc ]
initWithContentsOfFile: imgName ];
return image;
}
@end
Ya sÛlo queda compilar la aplicaciÛn. Bueno, y otro paso m·s. Habr· que empaquetarla para distribuirla. Para ello, crearemos un archivo dmg que contendr· la aplicaciÛn y un archivo de texto con las instrucciones de instalaciÛn.
Crearemos ese dmg con la Utilidad de Discos ( /Aplicaciones/Utilidades/Utilidad de discos ). Abre la utilidad de discos, crea una nueva imagen de disco, asigna el espacio de dicha imagen, y se crear· y montar·. Arrastra dentro de la imagen el bundle de la aplicaciÛn y el resto de archivos a incluir en la distribuciÛn, y °listo!
Hay que ver lo atrevida que es la ignorancia...
Comentarios
Te han faltado cosas, como quÈ es lo que va en Diche.h y DiceController.h asÌ como echar los pngs en el proyecto, etc. Al final se queda uno con las ganas de ver rodar la criaturita, pero vamos, gracias de todas formas, hacen falta tutoriales sencillos, m·s sencillos a˙n. La programaciÛn en Cocoa ya es rara de por sÌ y el entorno llega casi al esoterismo.
Publicado por: ende | Junio 30, 2005 02:19 PM
Bueno, comprobarÈ el empaquetado del proyecto, pero las cabeceras deberÌa estar ahÌ, al igual que los png.
Luego lo echarÈ un vistazo, y lo actualizo si es necesario.
Publicado por: Cesar Tardaguila | Junio 30, 2005 02:51 PM
FILE > PRINT > OK !
Gracias por esta introduccion !
Publicado por: afrael | Junio 30, 2005 09:36 PM
A pesar que lo haces ver f·cil, se me ha hecho muy difÌcil aprender a usar el Xcode y el CodeWarrior, podrÌas sugerirme algun sitio con documentaciÛn o libros para la iniciaciÛn en Xcode y/o CodeWarrior, los lenguajes los conozco, pero no se usar los editores
Publicado por: Teddy Dennis | Julio 4, 2005 05:23 AM
Pues no sÈ de ning˙n libro sobre XCode. Lo ˙nico que se me ocurre es utilizar la ayuda del propio XCode ( Comando-? ), donde est· el manual del programa.
Publicado por: Cesar Tardaguila | Julio 4, 2005 08:43 AM
Pues gracias por el tuto, pero la verdad es que me perdÌ varias veces. El problema que tengo es el mismo que el camarada de arriba, no se usar XCode.
A˙n asÌ se agradece el esfuerzo.
Publicado por: Sergio De Luna | Agosto 5, 2005 07:48 AM