<?xml version="1.0" encoding="iso-8859-1"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:admin="http://webns.net/mvcb/"
xmlns:cc="http://web.resource.org/cc/"
xmlns="http://purl.org/rss/1.0/">

<channel rdf:about="http://www.design-nation.net/es/">
<title>design-nation.blog/es</title>
<link>http://www.design-nation.net/es/</link>
<description>un blog sobre actionscript, java, cocoa, y lo que se tercie</description>
<dc:language>en-us</dc:language>
<dc:creator></dc:creator>
<dc:date>2008-08-28T10:05:16+00:00</dc:date>
<admin:generatorAgent rdf:resource="http://www.movabletype.org/?v=3.2" />


<items>
<rdf:Seq><rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003842.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003841.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003840.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003839.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003838.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003837.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003836.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003835.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003834.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003833.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003832.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003831.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003830.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003829.php" />
<rdf:li rdf:resource="http://www.design-nation.net/es/archivos/003828.php" />
</rdf:Seq>
</items>

</channel>

<item rdf:about="http://www.design-nation.net/es/archivos/003842.php">
<title>Keep Your Word ya está disponible pirateado</title>
<link>http://www.design-nation.net/es/archivos/003842.php</link>
<description>
<![CDATA[<p><img src="http://www.design-nation.net/es//kyw_cracked.png" alt="kyw_cracked.png" border="0" width="338" height="107" /></p>

<p>Espero que entiendan que no pase la respuesta con el link a la descarga...</p>

<p>Sigo pensando <a href="http://www.design-nation.net/es/archivos/003827.php">lo que pensaba hace unos meses</a>. Sigo creyendo que no merece la pena dejar de invertir tiempo y esfuerzo en mejorar la aplicación para dedicarlo a jugar al ratón y al gato durante un tiempo indefinido.</p>

<p>Y, honestamente, un poquito sí que se me ha hinchado el ego...</p>]]>

</description>
<dc:subject>General</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-08-28T10:05:16+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003841.php">
<title>Keep Your Word 1.0.1</title>
<link>http://www.design-nation.net/es/archivos/003841.php</link>
<description>
<![CDATA[<p>Release de mantenimiento de Keep Your Word, que soluciona los bugs reportados por los usuarios. Puede descargarse desde la propia aplicación, o bien <a href="http://www.bambooapps.com/appcasts/kyw.zip">a través de este enlace</a>.</p>

<p>La lista de cambios es:</p>

<p>	<h2>Keep Your Word 1.0.1</h2><br />
    <ul><br />
      <br />
        <li><strong>Bug #87</strong>: Solucionado un crash al arrancar los modos de ejercicios en documentos vacíos</li><br />
      <br />
        <li><strong>Bug #88</strong>: Solucionado un crash al editar la barra de herramientas</li><br />
      <br />
        <li><strong>Bug #90</strong>: Se podían añadir palabras mientras se estaban realizando ejercicios</li><br />
      <br />
        <li><strong>Bug #92</strong>: Nuevos atajos de teclado para el modo Flash Cards: T para girar la tarjeta, y cursor derecho e izquierdo para navegar entre las mismas.</li><br />
      <br />
        <li><strong>Bug #93</strong>: Los ítems de menú para borrar grupos y palabras se han trasladado al menú Edit</li><br />
      <br />
        <li><strong>Feature #89</strong>: Campo de búsqueda más grande</li><br />
      <br />
    </ul></p>

<p>Muchas gracias a todos los que habéis contactado con nosotros, sea para reportar bugs o para sugerir nuevas funcionalidades. Hemos recibido muchísimas buenas ideas que estamos deseando comenzar a implementar.</p>]]>

</description>
<dc:subject>Flash-Actionscript</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-08-27T07:52:13+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003840.php">
<title>Keep Your Word 1.0</title>
<link>http://www.design-nation.net/es/archivos/003840.php</link>
<description>
<![CDATA[<p>Esta vez ha sido niña.</p>

<p>Tengo el placer de anunciar la disponibilidad inmediata de la segunda aplicación de <a href="http://bambooapps.com/">bambooapps</a>: <a href="http://bambooapps.com/kyw/">Keep Your Word</a>.</p>

<p><img src="http://www.design-nation.net/es//kyw_interface_400.jpg" alt="kyw_interface_400.jpg" border="0" width="400" height="404" /></p>

<p>¿Para qué sirve Keep Your Word? Pues no es más que una herramienta de apoyo para los que estudiamos idiomas. Permite crear tus propios diccionarios, con los términos que tú quieras, y organizados como tú quieras. Pero además, facilita el aprendizaje de esas colecciones de palabras gracias a sus diferentes "modos de ejercicio".</p>

<p>Keep Your Word es una aplicación sólo para Mac OS X Leopard, tiene un período de prueba de 30 días, durante los cuales la aplicación es completamente funcional, y un precio de $24.95 USD.</p>

<p>Más información en la <a href="http://bambooapps.com/">web de bambooapps</a>.</p>]]>

</description>
<dc:subject>Cocoa</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-08-18T09:19:58+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003839.php">
<title>FND 1.3</title>
<link>http://www.design-nation.net/es/archivos/003839.php</link>
<description>
<![CDATA[<p>Se acaba de liberar una nueva versión de <a href="http://bambooapps.com/fnd/">FND (film is not dead)</a>, 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.</p>

<p><img src="http://www.design-nation.net/es//fnd_1_4_450.png" alt="fnd_1_4_450.png" border="0" width="450" height="381" /></p>

<p>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.</p>

<p>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.</p>

<p>Esta nueva versión permite al usuario asignar los tiempos de agitación, que por defecto se sitúan en 30 segundos tanto en la importación inicial de datos como en la creación de nuevos registros, así como algunos bugfixes.</p>]]>

</description>
<dc:subject>Cocoa</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-07-17T13:39:28+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003838.php">
<title>Nueve meses</title>
<link>http://www.design-nation.net/es/archivos/003838.php</link>
<description>
<![CDATA[Es el tiempo que ha necesitado flickr para aprobar una solicitud de API comercial.

Nota mental número uno: jamás, nunca jamás, vuelvas a depender de un servicio externo para tus desarrollos.

Nota mental número dos: el próximo que diga "mashup" delante de mí se va a llevar un bofetón. Algo que tampoco debe descartar el próximo que, delante de mí, vuelva a decir "webdospuntocero".

Obviamente, <a href="http://bambooapps.com/arriba/">el proyecto</a>, a estas alturas, tiene una capa de polvo de un metro de grosor. Lo que tampoco tiene porqué ser algo necesariamente malo. Veremos.]]>

</description>
<dc:subject>Flash-Actionscript</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-06-13T05:05:25+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003837.php">
<title>iPhone 3G</title>
<link>http://www.design-nation.net/es/archivos/003837.php</link>
<description>
<![CDATA[Apple nunca se ha caracterizado por utilizar la misma vara de medir los productos que utilizan el resto de fabricantes. Por eso, un teléfono caro y corto en funcionalidades en comparación con la competencia, lleva un año siendo el producto estrella de la compañía.

Imagino que hoy toda la web especializada en el cacharreo estará dándole mil vueltas a la lista de "cosas" que tiene el teléfono. Sinceramente, eso no creo que sea lo más importante del anuncio de ayer.

Desde mi punto de vista, lo más significativo es que la keynote de apertura de la WWDC se dedique prácticamente en exclusiva al lanzamiento de un producto y de un servicio (.Mac) remodelado en apoyo de ese producto. Porque eso es lo que da la idea real de dónde está Apple hoy en día, y de hacia dónde se va a seguir dirigiendo en el futuro cercano.

Tampoco creo que nadie se pueda engañar. Ya hace cosa de un año que sabemos que para Apple, el ordenador no es el producto estrella del catálogo, sino un producto más. Incluso, en breve, me temo, el ordenador será sólo la herramienta que los desarrolladores van a necesitar para trabajar en el "auténtico" producto Apple: el iPhone. Es lo que hay, guste o no.

Ahora bien, desde el punto de vista de un desarrollador que <a href="http://www.bambooapps.com">intenta vender aplicaciones</a>, hoy es un día para estar satisfechos. Apple deja el iPhone en un precio en el que es imposible resistirse (y hasta donde yo recuerdo, es la primera vez que un producto de Apple es más barato que la competencia), y nos permite distribuir aplicaciones a través de un canal embebido en el sistema, con coste cero para nosotros, y con exposición máxima. Dicho de otra forma, el Tito Estíf ha hecho todo lo posible para que sea casi obligatorio para cualquier desarrollador el plantearse seriamente el intentar construir algo para el iPhone.

En eso, ganamos todos. El que programa porque lo va a tener algo más fácil para intentar vender; Apple, porque se está asegurando la existencia de un amplio catálogo de aplicaciones; el usuario final, porque va a tener muchas cosas buenas donde elegir. 

Como mínimo, desde luego, a mí me han hecho replantearme si la idea en la que estoy trabajando va a ser finalmente para escritorio o para iPhone. Y es que no es lo mismo intentar vender una aplicación para una plataforma con un 3% de penetración que para lo que parece que va a ser el cacharro de la temporada.]]>

</description>
<dc:subject>Cocoa</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-06-10T02:48:39+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003836.php">
<title>Testing: Hopefully not nobody</title>
<link>http://www.design-nation.net/es/archivos/003836.php</link>
<description>
<![CDATA[<p>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í...</p>

<p><img src="http://www.design-nation.net/es//hopefully.png" alt="hopefully.png" border="0" width="364" height="414" /></p>

<p>"Hopefully not nobody". Tiene su chispa.</p>]]>

</description>
<dc:subject>Cocoa</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-04-23T10:33:03+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003835.php">
<title>FND 1.2</title>
<link>http://www.design-nation.net/es/archivos/003835.php</link>
<description>
<![CDATA[<p>Se acaba de liberar una nueva versión de <a href="http://bambooapps.com/fnd/">FND (film is not dead)</a>, 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.</p>

<p>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.</p>

<p>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.</p>

<p>Esta nueva versión incluye, entre varias mejoras de usabilidad, la localización en castellano.</p>]]>

</description>
<dc:subject>Cocoa</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-04-01T12:23:07+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003834.php">
<title>Uso de Core Animation para modificar el contenido de una vista</title>
<link>http://www.design-nation.net/es/archivos/003834.php</link>
<description>
<![CDATA[<p>Uno de los frameworks que han hecho su debut con Leopard ha sido Core Animation.</p>

<p>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.</p>

<p>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.</p>

<p>En este ejemplo vamos a partir de este primer estado:</p>

<p><img src="http://www.design-nation.net/es//swap_final_1.png" alt="swap_final_1.png" border="0" width="560" height="243" /></p>

<p>Para llegar a este otro:</p>

<p><img src="http://www.design-nation.net/es//swap_final_2.png" alt="swap_final_2.png" border="0" width="560" height="243" /></p>

<p>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).</p>

<p>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:</p>

<p><img src="http://www.design-nation.net/es//swap_ventana.png" alt="swap_ventana.png" border="0" width="560" height="243" /></p>

<p>Además, construyo dos instancias más de NSView:</p>

<p><img src="http://www.design-nation.net/es//swap_view1.png" alt="swap_view1.png" border="0" width="381" height="193" /></p>

<p><img src="http://www.design-nation.net/es//swap_view2.png" alt="swap_view2.png" border="0" width="243" height="198" /></p>

<p>Como se puede ver, el ancho de las dos vistas es diferente. </p>

<p>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:</p>

<p>#import <Cocoa/Cocoa.h></p>

<p><br />
@interface ViewSwapController : NSObject <br />
{<br />
	IBOutlet NSView *containerView;<br />
	IBOutlet NSView *firstView;<br />
	IBOutlet NSView *secondView;<br />
	<br />
	BOOL showFirst;<br />
}</p>

<p>-(IBAction) swapView: (id) sender;<br />
@end</p>

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

<p><img src="http://www.design-nation.net/es//swap_nib.png" alt="swap_nib.png" border="0" width="399" height="430" /></p>

<p>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.</p>

<p>Por tanto, el método awakeFromNib será:</p>

<p>-(void) awakeFromNib<br />
{	<br />
	showFirst = NO;<br />
	<br />
	[ containerView setWantsLayer: YES ];<br />
	<br />
	[ [ containerView animator ] addSubview: firstView ];<br />
}</p>

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

<p>Al hacer clic en el botón:</p>

<p>-(IBAction) swapView: (id) sender<br />
{<br />
	NSRect containerFrame = [ containerView frame ];<br />
	NSRect firstViewFrame;<br />
	NSNumber *newCoord;<br />
	NSView *tempFirst;<br />
	NSView *tempSecond;<br />
	<br />
	if( showFirst )<br />
	{<br />
		tempFirst = secondView;<br />
		tempSecond = firstView;<br />
		<br />
		showFirst = NO;<br />
	}<br />
	else<br />
	{<br />
		tempFirst = firstView;<br />
		tempSecond = secondView;<br />
		<br />
		showFirst = YES;<br />
	}<br />
	<br />
	[ [ containerView animator ] replaceSubview: tempFirst with: tempSecond ];		<br />
	<br />
	firstViewFrame = [ tempSecond frame ];<br />
	<br />
	newCoord = [ NSNumber numberWithFloat: containerFrame.size.width /2 - firstViewFrame.size.width/2 ];</p>

<p>	[ tempSecond setFrameOrigin: NSMakePoint( [ newCoord intValue ] , 0 ) ];		<br />
	</p>

<p>}</p>

<p><br />
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.</p>

<p>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.</p>

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

<p>svn co http://svn.liadorasoft.com/viewswap ViewSwap</p>

<p>Enlaces relacionados:<br />
<a href="http://www.design-nation.net/es/archivos/003819.php">Un clon de Photo Booth en 32 minutos</a><br />
<a href="http://www.design-nation.net/es/archivos/003829.php">Extensión por delegación</a><br />
<a href="http://www.design-nation.net/es/archivos/003830.php">Bindings, NSArrayController y Value Transformers</a></p>]]>

</description>
<dc:subject>Cocoa</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-03-19T04:36:35+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003833.php">
<title>iPhone SDK</title>
<link>http://www.design-nation.net/es/archivos/003833.php</link>
<description>
<![CDATA[<p>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.</p>

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

<p><strong>¿Documentación?</strong><br />
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.</p>

<p>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.</p>

<p><strong>No es el iPhone ni el iPod, es lo que está por venir</strong><br />
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 <em>la plataforma de Apple para dispositivos con pantalla táctil</em>.</p>

<p>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.</p>

<p>Y eso está muy bien.</p>

<p><strong>Cuota de mercado</strong><br />
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. </p>

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

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

<p><strong>Modelo de distribución</strong><br />
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.</p>

<p>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.</p>

<p>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.</p>

<p>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.</p>

<p><strong>El flujo de trabajo</strong><br />
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.</p>

<p>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.</p>

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

<p>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...</p>]]>

</description>
<dc:subject>Cocoa</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-03-07T04:26:06+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003832.php">
<title>FND 1.1.1</title>
<link>http://www.design-nation.net/es/archivos/003832.php</link>
<description>
<![CDATA[<p><a href="http://bambooapps.com/2008/02/10/fnd-111/">Release de mantenimiento</a> 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.</p>

<p>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.</p>

<p>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.</p>]]>

</description>
<dc:subject>Cocoa</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-02-10T12:42:03+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003831.php">
<title>Entresijos. Haciendo la web. El nuevo proyecto de Design-Nation</title>
<link>http://www.design-nation.net/es/archivos/003831.php</link>
<description>
<![CDATA[<p>Durante los próximos días, tomará cuerpo "<a href="http://www.design-nation.net/entresijos/">Entresijos. Haciendo la web</a>", el nuevo y por ahora último proyecto que sale de la cocina de ideas del emporio Design-Nation.</p>

<p>¿Qué es "Entresijos" ?</p>

<p>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.</p>

<p>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.</p>

<p>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.</p>

<p>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.</p>

<p>Esperamos que os guste. </p>]]>

</description>
<dc:subject>General</dc:subject>
<dc:creator>Javier Tardaguila</dc:creator>
<dc:date>2008-01-31T18:33:55+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003830.php">
<title>Bindings, NSArrayController y Value Transformers</title>
<link>http://www.design-nation.net/es/archivos/003830.php</link>
<description>
<![CDATA[<p>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.</p>

<p>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.</p>

<p>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".</p>

<p>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".</p>

<p>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:</p>

<p>#import <Cocoa/Cocoa.h></p>

<p><br />
@interface AppController : NSObject <br />
{<br />
	NSMutableArray *iconsCollection;<br />
}</p>

<p>@property(copy, readwrite) NSMutableArray *iconsCollection;</p>

<p>@end</p>

<p>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.</p>

<p><img src="http://www.design-nation.net/es//interfaz_transformer.png" alt="interfaz_transformer.png" border="0" width="210" height="460" /></p>

<p>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". </p>

<p>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?"</p>

<p>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!":</p>

<p>[ NSImage imageNamed: @"NSComputer" ];</p>

<p>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?</p>

<p>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.</p>

<p>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.</p>

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

<p>#import <Cocoa/Cocoa.h></p>

<p><br />
@interface AppEntity : NSObject <br />
{<br />
	NSString *iconName;<br />
}<br />
@property(copy, readwrite) NSString *iconName;<br />
@end</p>

<p><br />
La implementación:</p>

<p>#import "AppEntity.h"</p>

<p><br />
@implementation AppEntity<br />
@synthesize iconName;<br />
@end</p>

<p><br />
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á:</p>

<p>#import "AppController.h"<br />
#import "AppEntity.h"<br />
#import "DNIconValueTransformer.h"</p>

<p><br />
@implementation AppController<br />
@synthesize iconsCollection;<br />
-(id) init<br />
{<br />
	self = [ super init ];<br />
	<br />
	NSValueTransformer *iconTransformer = [ [ DNIconValueTransformer alloc ] init ];<br />
	[ NSValueTransformer setValueTransformer: iconTransformer forName:@"IconImageTransformer"];		<br />
	<br />
	iconsCollection = [ [ NSMutableArray alloc ] init ];<br />
	<br />
	AppEntity *entityOne = [ [ AppEntity alloc ] init ];<br />
	entityOne.iconName = @"NSComputer";<br />
	[ iconsCollection addObject: entityOne ];</p>

<p>	AppEntity *entityTwo = [ [ AppEntity alloc ] init ];<br />
	entityTwo.iconName = @"NSFolderBurnable";<br />
	[ iconsCollection addObject: entityTwo ];</p>

<p>	AppEntity *entityThree = [ [ AppEntity alloc ] init ];<br />
	entityThree.iconName = @"NSFolderSmart";	<br />
	[ iconsCollection addObject: entityThree ];	<br />
	<br />
	return self;<br />
}<br />
@end</p>

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

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

<p>#import <Cocoa/Cocoa.h></p>

<p><br />
@interface DNIconValueTransformer : NSValueTransformer<br />
{</p>

<p>}</p>

<p>@end</p>

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

<p>La implementación tiene un poco más de miga:</p>

<p>#import "DNIconValueTransformer.h"</p>

<p><br />
@implementation DNIconValueTransformer</p>

<p>+ (Class)transformedValueClass<br />
{<br />
	return [ NSImage class ]; <br />
}</p>

<p>+ (BOOL)allowsReverseTransformation<br />
{<br />
	return YES;<br />
}</p>

<p>- ( id ) transformedValue:( id )value<br />
{<br />
		NSLog( @"transformador %@", value );<br />
		<br />
		if( value != nil )<br />
		{<br />
			return [ NSImage imageNamed: value ];<br />
		}<br />
		else<br />
		{<br />
			NSLog( @"pasa por el transformador" );<br />
			return nil;<br />
		}<br />
}</p>

<p>@end</p>

<p>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.</p>

<p>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.</p>

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

<p><img src="http://www.design-nation.net/es//controlador_Array.png" alt="controlador_Array.png" border="0" width="450" /></p>

<p>El último paso es asignar el binding de la columna de la tabla. </p>

<p><img src="http://www.design-nation.net/es//table_column_bindings.png" alt="table_column_bindings.png" border="0" width="299" height="380" /></p>

<p>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.</p>

<p>De esa forma, el resultado final es el que se pretendía conseguir:</p>

<p><img src="http://www.design-nation.net/es//icons_final.png" alt="icons_final.png" border="0" width="210" height="460" /></p>

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

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

<p>El proyecto completo puede descargarse de <a href="http://www.design-nation.net/es/archivos/transformers.zip">este enlace</a></p>]]>

</description>
<dc:subject>Cocoa</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-01-23T10:07:44+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003829.php">
<title>Extensión por delegación</title>
<link>http://www.design-nation.net/es/archivos/003829.php</link>
<description>
<![CDATA[<p><br />
<strong>Gran Maestro</strong>: <em>La prueba de hoy en el largo y tortuoso camino del conocimiento, Gran Dragón, es programar una vista clickable, que puedas reutilizar en todas las futuras pruebas con las que te vas a encontrar, y que sea capaz de notificar al controlador de la aplicación en la que se esté utilizando cada uno de los clicks que reciba.<br />
</em></p>

<p><strong>Gran Dragón</strong>: <em>Gracias, Gran Maestro, por proponerme un reto de tal importancia.<br />
</em></p>

<p>El Gran Dragón sabe que no puede traicionar la confianza ni las expectatias de su maestro. Sabe que ha comenzado un largo camino, un camino lleno de escarpadas montañas, cruzado por anchos y profundos ríos, un camino del que parten otros muchos caminos que le pueden distraer de su objetivo final: llegar al estado mental en el que sólo hay una forma de pensar; la que termina con la máxima cohesión y el mínimo acoplamiento.</p>

<p>Por eso, y porque El Gran Dragón cree que la mejor forma de programar es iterativa, produciendo desde la primera iteración algo funcional, aunque no esté necesariamente muy refinado, comienza su aventura declarando una subclase de NSView, que, simplemente, sea capaz de capturar los clicks de ratón que se produzcan sobre ella. Además, El Gran Dragón quiere proporcionar feedback visual de las interacciones con su vista, por lo que va a hacer que la vista cambie de color, del gris en reposo, a un gris más claro cuando sea clickada.</p>

<p>Por tanto, la cabecera de su vista será:</p>

<p>#import <Cocoa/Cocoa.h></p>

<p><br />
@interface DNClickableView : NSView <br />
{<br />
	BOOL mouseIsPressingMe;<br />
}</p>

<p>@end</p>

<p><br />
Al inicializar la instancia de su clase, el Gran Dragón hará que la variable booleana valga false. Cada vez que redibuje el contenido de su vista, comprobará el valor de esa variable: si es true, el fondo será gris claro, y si es false, gris:</p>

<p>- (id)initWithFrame:(NSRect)frame <br />
{<br />
    self = [super initWithFrame:frame];<br />
	<br />
    if (self) <br />
	{<br />
		mouseIsPressingMe = NO;<br />
    }<br />
	<br />
    return self;<br />
}</p>

<p>- (void)drawRect:(NSRect)rect <br />
{<br />
    if ( mouseIsPressingMe )<br />
	{<br />
		[ [ NSColor lightGrayColor ] set ];<br />
	}<br />
	else<br />
	{ <br />
		[ [ NSColor grayColor ] set ];<br />
	}<br />
	<br />
    NSRectFill( rect );<br />
}</p>

<p><br />
Para capturar los eventos de ratón sobre esa vista, basta con declararlos, sobreescribiendo por tanto los correspondientes a NSView, en la implementación de la subclase:</p>

<p>- ( void ) mouseDown: ( NSEvent * ) theEvent <br />
{<br />
	mouseIsPressingMe = YES;<br />
	[ self setNeedsDisplay: YES ];<br />
}</p>

<p>- (void)mouseUp:(NSEvent *)theEvent <br />
{<br />
    mouseIsPressingMe = NO;<br />
    [ self setNeedsDisplay: YES ];<br />
}</p>

<p>Por tanto, la declaración completa de la implementación de la clase sería:</p>

<p>#import "DNClickableView.h"</p>

<p><br />
@implementation DNClickableView</p>

<p>- (id)initWithFrame:(NSRect)frame <br />
{<br />
    self = [super initWithFrame:frame];<br />
	<br />
    if (self) <br />
	{<br />
		mouseIsPressingMe = NO;<br />
    }<br />
	<br />
    return self;<br />
}</p>

<p>- (void)drawRect:(NSRect)rect <br />
{<br />
    if ( mouseIsPressingMe )<br />
	{<br />
		[ [ NSColor lightGrayColor ] set ];<br />
	}<br />
	else<br />
	{ <br />
		[ [ NSColor grayColor ] set ];<br />
	}<br />
	<br />
    NSRectFill( rect );<br />
}</p>

<p>#pragma mark -<br />
#pragma mark mouse handling</p>

<p>- ( void ) mouseDown: ( NSEvent * ) theEvent <br />
{<br />
	mouseIsPressingMe = YES;<br />
	[ self setNeedsDisplay: YES ];<br />
}</p>

<p>- (void)mouseUp:(NSEvent *)theEvent <br />
{<br />
    mouseIsPressingMe = NO;<br />
    [ self setNeedsDisplay: YES ];<br />
}<br />
@end</p>

<p><br />
El Gran Dragón sabe que debe testar mucho y desde muy pronto, por lo que, para probar la funcionalidad de su clase, declara un controlador con un outlet hacia su vista, y compila y prueba el proyecto (El Gran Dragón da por supuesto que le lector sabe cómo hacer eso en XCode 3; no obstante, se puede encontrar <a href="http://www.design-nation.net/es/archivos/003819.php">más información sobre cómo hacerlo aquí</a>)</p>

<p>Bien, el Gran Dragón está satisfecho de su primera iteración. Tiene una aplicación que compila aunque no cumple con uno de los requisitos pedidos: que la vista notifique al controlador los clicks recibidos.</p>

<p>Ahora ha llegado el momento de meditar, con la cabeza fría, sobre los diferentes caminos que se presentan ante el Gran Dragón.</p>

<p>El primer camino, el más obvio, y probablemente el más sencillo y rápido de implementar sería declarar una variable de clase en la vista, en la que guardar una referencia al controlador, de forma que, al capturar el clic, se envíe un mensaje al controlador de la aplciación.</p>

<p>No está mal, piensa El Gran Dragón. Sin embargo, ¿hasta qué punto esa solución es portable? ¿Hasta qué punto esa misma vista se podría reutilizar en más proyectos?</p>

<p>El Gran Dragón sonríe, con la satisfacción de saberse en el buen camino. Sabe que esa primera solución, la más rápida, es, probablemente, la menos adecuada. En primer lugar, porque implica que tanto la vista como el controlador tengan una referencia cruzada el uno al otro. </p>

<p>En segundo lugar, porque si se hacen las cosas como se debería, la referencia al controlador que se guarda en la vista debería estar declarada con el tipo del controlador. Lo que no la hace precisamente portable. Claro, que eso se podría solventar haciendo que esa referencia sea de tipo un protocolo que implemente el controlador. Lo que tampoco es bastante portable, porque obliga a que el controlador de cualquier aplicación que quiera utilizar esta vista deba implementar ese protocolo.</p>

<p>El Gran Dragón, por tanto, deshecha la primera solución.</p>

<p>La segunda solución que le viene a la cabeza es utilizar una notificación, de forma que la vista lance esa notificación (lo que en la mayoría de lenguajes se llama un evento), que será escuchada por el controlador.</p>

<p>El problema en esta segunda solución es que la implementación de las notificaciones en Objective-C es un poco particular. Las notificaciones se emiten y se reciben a través de un singleton (NSNotificationCenter) de forma que es relativamente sencillo pisarse un pie con el otro, y hacer que una notificación sea escuchada por quien no debe.</p>

<p>Además, las notificaciones hacen el código un poco más difícil de leer, y tampoco es que sean demasiado amigables a la hora de pasar parámetros. </p>

<p>El Gran Dragóm, por tanto, inmerso como está en la búsqueda de la elegancia en su código, deshecha la segunda solución.</p>

<p>La tercera solución, sin embargo, es utilizar uno de los patrones más comunes en Cocoa: la delegación.</p>

<p>La extensión por delegación no es más que una forma de composición un poco más sofisticada. Una clase, la que se quiere extender, puede delegar detalles concretos de implementación (lo que es susceptible de cambiar entre una utilización y otra de la clase) en otras clases, de forma que, en tiempo de ejecución, se pueden delegar responsabilidades en clases concretas declaradas a ese efecto.</p>

<p>Ese patrón es muy sencillo de implementar en Objective-C, como bien sabe El Gran Dragón, gracias a la naturaleza tan dinámica del lenguaje, y a que siempre se puede saber si una clase va a poder responder o no a un mensaje.</p>

<p>El Gran Dragón comienza, por tanto, la escalada de la delegación declarando una variable de clase en la vista, junto con sus accesors:</p>

<p>#import <Cocoa/Cocoa.h></p>

<p><br />
@interface DNClickableView : NSView <br />
{<br />
	BOOL mouseIsPressingMe;<br />
	id delegate;<br />
}</p>

<p>- (id) delegate;<br />
- (void) setDelegate: (id) newDelegate;</p>

<p>-(void) viewWasClicked;<br />
@end</p>

<p>Además, declara un método que será ejecutado cuando se haga click en la vista (viewWasClicked)</p>

<p>Por tanto, los métodos dedicados a la captura de los clics quedarían así:</p>

<p>- ( void ) mouseDown: ( NSEvent * ) theEvent <br />
{<br />
	mouseIsPressingMe = YES;<br />
	[ self setNeedsDisplay: YES ];<br />
}</p>

<p>- (void)mouseUp:(NSEvent *)theEvent <br />
{<br />
    mouseIsPressingMe = NO;<br />
    [ self setNeedsDisplay: YES ];<br />
	<br />
	[ self viewWasClicked ];<br />
}</p>

<p>Los acessors para el delegate:<br />
- (id)delegate<br />
{<br />
	return delegate;<br />
}</p>

<p>- (void)setDelegate:(id)newDelegate <br />
{<br />
	delegate = newDelegate;<br />
}</p>

<p>El método que gestiona los clicks:</p>

<p>-(void) viewWasClicked<br />
{<br />
	if( [ delegate respondsToSelector: @selector( viewWasClicked ) ] )<br />
	{<br />
		[ delegate viewWasClicked ];<br />
	}<br />
}</p>

<p>Ahí es donde el Gran Dragón se siente más orgulloso. Para evitar estar enviando mensajes a nil, comprueba que lo que se haya asignado como delegate responde al mensaje viewWasClicked. En caso de responder, reenvía el mensaje a esa clase, y en caso de no responder a él, lo deja morir.</p>

<p>En el controlador, sólo faltaría asignar el delegate:</p>

<p>-(void) awakeFromNib<br />
{<br />
	[ clickView setDelegate: self ];<br />
}</p>

<p><br />
Por tanto, la implementación completa de la vista sería:</p>

<p>#import "DNClickableView.h"</p>

<p><br />
@implementation DNClickableView</p>

<p>- (id)initWithFrame:(NSRect)frame <br />
{<br />
    self = [super initWithFrame:frame];<br />
	<br />
    if (self) <br />
	{<br />
        // Initialization code here.<br />
		<br />
		mouseIsPressingMe = NO;<br />
    }<br />
	<br />
    return self;<br />
}</p>

<p>- (void)drawRect:(NSRect)rect <br />
{<br />
    if ( mouseIsPressingMe )<br />
	{<br />
		[ [ NSColor lightGrayColor ] set ];<br />
	}<br />
	else<br />
	{ <br />
		[ [ NSColor grayColor ] set ];<br />
	}<br />
	<br />
    NSRectFill( rect );<br />
}</p>

<p>#pragma mark -<br />
#pragma mark mouse handling</p>

<p>- ( void ) mouseDown: ( NSEvent * ) theEvent <br />
{<br />
	mouseIsPressingMe = YES;<br />
	[ self setNeedsDisplay: YES ];<br />
}</p>

<p>- (void)mouseUp:(NSEvent *)theEvent <br />
{<br />
    mouseIsPressingMe = NO;<br />
    [ self setNeedsDisplay: YES ];<br />
	<br />
	[ self viewWasClicked ];<br />
}</p>

<p><br />
#pragma mark -<br />
#pragma mark delegate handling</p>

<p>- (id)delegate<br />
{<br />
	return delegate;<br />
}</p>

<p>- (void)setDelegate:(id)newDelegate <br />
{<br />
	delegate = newDelegate;<br />
}</p>

<p>-(void) viewWasClicked<br />
{<br />
	if( [ delegate respondsToSelector: @selector( viewWasClicked ) ] )<br />
	{<br />
		[ delegate viewWasClicked ];<br />
	}<br />
}</p>

<p><br />
-(void) dealloc<br />
{<br />
	[ delegate release ];<br />
	[ super dealloc ];<br />
}<br />
@end</p>

<p><br />
y la del controlador:</p>

<p>@implementation DNAppController</p>

<p>-(void) awakeFromNib<br />
{<br />
	[ clickView setDelegate: self ];<br />
}</p>

<p>#pragma mark -<br />
#pragma mark DNClickableView delegate method</p>

<p>-(void) viewWasClicked<br />
{<br />
	NSLog( @"DNAppController.viewWasClicked" );<br />
}<br />
@end</p>

<p><br />
Mucho mejor. El Gran Dragón se siente satisfecho, porque aunque aparentemente haya implementado una solución similar a la primera que deshechó, ha ganado muchísimo en flexibilidad. En este ejemplo, el delegate se ha asignado al controlador, pero podría ser cualquier clase, instanciada directamente en el controlador, o producto de algún patrón de creación.</p>

<p>Sin embargo, el Gran Dragón sabe que su Gran Maestro, hombre noble y de infinita sabiduría pero muy exigente, no va a ver con buenos ojos que haya declarado la referencia al delegate como id, sin más.</p>

<p>Objective-C soporta protocolos, por lo que el método que se va a delegar, podría estar declarado en un protocolo, en un protocolo informal en realidad. ¿Porqué informal? Porque de esa forma no se obliga a nadie que lo cumpla a que implemente todos los métodos declarados en el mismo.</p>

<p>Por cierto, El Gran Dragón sabe que su solución está un pelín obsoleta con la introducción de Objective-C 2.0, ya que los ingenieros de Apple recomiendan que en la nueva iteración del lenguaje no se utilicen protocolos informales, sino que prefieren que se utilicen protocolos formales con métodos opcionales.</p>

<p>No obstante, El Gran Dragón quiere terminar con el proyecto, porque fuera del templo brilla el sol y le apetece salir a hacer fotos, así que comienza por declarar el protocolo informal, en la cabecera de la vista:</p>

<p>@interface DNClickableView : NSView <br />
{<br />
	BOOL mouseIsPressingMe;<br />
	id  delegate;<br />
}</p>

<p>- (id) delegate;<br />
- (void) setDelegate: (id) newDelegate;</p>

<p>@end</p>

<p>@interface NSObject ( DNClickableViewDelegate )<br />
-(void) viewWasClicked;<br />
@end</p>

<p><br />
De esa forma, el compilador creerá que todos los objetos conforman ese protocolo, aunque en realidad, al ser informal, no tienen porqué implementar el método declarado en él.</p>

<p>El Gran Dragón está contento. Su subclase de NSView puede reutilizarse en todos los proyectos, porque no está vinculada a ningún controlador concreto, ni siquiera a un interfaz de éste, y lo que es mejor, la funcionalidad que se quiere asignar al click del ratón, que puede ser diferente en cada caso, puede estar encapsulada en una clase que se le proporciona a la vista, sin que ésta sepa nada de ella, ni de sus detalles de implementación, ni de su forma de creación.</p>

<p>El Gran Maestro, mientras tanto, mira orgulloso a su pupilo, pensando ya en el próximo reto...</p>]]>

</description>
<dc:subject>Cocoa</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-01-08T05:47:46+00:00</dc:date>
</item>
<item rdf:about="http://www.design-nation.net/es/archivos/003828.php">
<title>Instalación de git en Mac OS X 10.5 Leopard</title>
<link>http://www.design-nation.net/es/archivos/003828.php</link>
<description>
<![CDATA[<p>Como estoy hasta el gorro de las peleas a brazo partido con Subversion, he decidido comenzar a utilizar <a href="http://git.or.cz/">git</a> para los proyectos nuevos.</p>

<p>La instalación de git en Leopard (Mac OS X 10.5.1) es muy sencilla. </p>

<p>El primer paso es descargar el tar con la última versión (a día de hoy la 1.5.3.7), y descomprimirlo (ya desde el Terminal):</p>

<p>tar xvzf git-1.5.3.7.tar.gz</p>

<p>A continuación, desde la carpeta generada al descomprimir el tar:</p>

<p>make configure<br />
./configure --prefix=/usr/local<br />
make all<br />
sudo make install</p>

<p>Y listo. Ya se pueden borrar tanto el tar como la carpeta donde éste se descomprimió.</p>]]>

</description>
<dc:subject>Cocoa</dc:subject>
<dc:creator>Cesar Tardaguila</dc:creator>
<dc:date>2008-01-06T13:21:52+00:00</dc:date>
</item>


</rdf:RDF>