Objetos distribuidos en Cocoa usando NSConnection y NSProxy

diciembre 11, 2010

Cuando nuestros programas crecen lo suficiente, nos encontramos con situaciones donde tenemos varios hilos de ejecución o incluso diferentes procesos que se ejecutan de forma paralela en la misma o en diferente máquina. En estas situaciones, es habitual tener que comunicar estos diferentes módulos.

Una típica forma de comunicación es el uso de objetos “distribuidos”, desde los vetustos (y terroríficos :)) objetos CORBA, pasando por RMI de Java o Remoting de .NET, hasta los mas modernos WebServices, estos mecanismos han sido y son ampliamente utilizados.

Explicado de una forma muy simple, estos mecanismos permiten llamar a un método de una instancia de un objeto que no se esta ejecutando en el mismo entorno que el llamador. Ese entorno puede ser otro hilo, otro proceso u otra máquina.

Como era de esperar, Cocoa plantea su aproximación al uso de objetos distribuidos. Como hemos hablado anteriormente en el blog, el mecanismo de invocación de métodos en Objetive-c basado en mensajes, ayuda a entender y a enfocar de otra manera el funcionamiento de la invocación remota de métodos de objetos.

En un lenguaje como Java, cuando invocas a un método remoto, realmente estas invocando a un método que tiene que existir en una clase “local”. Esta clase “local” habitualmente es un Proxy que se autogenera estáticamente. El Proxy por su parte, transforma la llamada en una comunicación con el servidor remoto, que se encarga de invocar el método y devolver el retorno.

En Objetive-C, una llamada a un objeto remoto, se traduce en un mensaje que se “enruta” hasta llegar al objeto receptor. En este caso, el Proxy no es necesario autogenerarlo, pues como hablamos, el Proxy será un objeto que es capaz de recibir en tiempo de ejecución cualquier tipo de mensaje. No tenemos la necesidad de que el método realmente exista para poder compilar nuestro código.

Las clases que entran en juego son numerosas, y el funcionamiento completo tiene su “intríngulis” :), por lo que en este post nos centraremos en el aspecto mas práctico, es decir, poner un ejemplo de como funciona.

El código se divide en dos partes, por un lado esta el objeto que va e estar ejecutandose en modo “servidor” y por otro, el lado del cliente.

Hablando del servidor, vamos a tener un objeto de tipo “Calculadora” que va a tener un método “addNumber:with:”, que como dice su nombre, sumará dos números. A este objeto lo vamos a llamar de forma remota.

@protocol CalculatorProtocol
- (int) addNumber:(int) a with:(int)b;
@end

@interface Calculator : NSObject<CalculatorProtocol> {
}
@end

El protocolo, nos va a ayudar a que el proxy sepa que el método existe. Realmente esto no es estrictamente necesario, ya que el mensaje se enrutará de todas maneras hasta llegar a la clase Calculator, pero sin embargo es una buena ayuda de cara a la comprobación que el runtime hace para saber si la clase remota responde o no al mensaje.

Una vez que tenemos el objeto que queremos exportar, necesitamos publicarlo, o como se llama en la documentación: “Vending an Object”.

Para ello, vamos a hacer uso de la clase NSConnection

Calculator* calculator = [[Calculator alloc] init];
NSConnection* theConnection = [[[NSConnection alloc] init] autorelease];
[theConnection setRootObject:calculator];
[theConnection registerName:@"calculator"];

[[NSRunLoop currentRunLoop] run]; 
 // Solo si nuestra aplicación no lo ha hecho ya
 // En caso de una aplicación Cocoa, esto no es necesario

Con esas 5 lineas, nuestro Servidor ya estará escuchando peticiones, y el objeto estará listo para usarse desde otro entorno de ejecución, fácil, ¿no?.

La parte cliente, no es que sea mucho mas compleja 😉

id theProxy;
theProxy = [[NSConnection rootProxyForConnectionWithRegisteredName:@"calculator" host:nil] retain];
[theProxy setProtocolForProxy:@protocol(CalculatorProtocol)];
NSLog(@"%d", [theProxy addNumber:5 with:3]);

Una vez mas el objeto NSConnection nos va a servir para obtener la conexión al objeto remoto. Usamos la misma cadena que se utilizó en el registro, y pasamos “nil” al parámetro host, ya que en este ejemplo, el servidor esta en la misma máquina.

Ambos fragmentos de código se ejecutan en procesos diferentes, y como se espera, el resultado del cliente es imprimir un 8 en la pantalla de logs.

Sin duda, el post no ataca toda la complejidad que hay detrás de los mecanismos, y las diferentes alternativas que existen de cara a la configuración de la conexión u otros aspectos que entran en juego, pero aún así se puede ver lo sencillo que es invocar un mensaje sobre un objeto que esta ejecutandose fuera de nuestro proceso.

Anuncios

Categoría para traducir entidades html en NSString

septiembre 20, 2010

Recientemente desarrollando para el iOS, me encontré con la necesidad de eliminar las entidades html de una cadena de texto.

Para el que no lo sepa, las entidades dentro de HTML, o en cualquier lenguage de marcas, son lo mas parecido a una secuencia de escape, es decir, una cadena que representa a un caracter que originalmente no esta permitido. Por ejemplo, y como parece obvio, si queremos poner el caracter ‘<‘ en HTML, no podemos ponerlo directamente, pues forma parte del propio lenguage. Por ello, si queremos escribir dicho carácter tendremos que poner <.

La principal característica de las entidades de un lenguage de marcas, es que comienzan con ‘&’ y acaban con ‘;’.

Dentro de la API de manejo de cadenas de UIKit, existe un método para codificar URLs, que aunque pueda parecer similar, no lo es. Pues las URLs no tienen nada que ver con el lenguage HTML, solo nos indican la forma de acceder a los documentos que estan hechos con HTML 😉

Dichos métodos son, stringByAddingPercentEscapesUsingEncoding: y stringByReplacingPercentEscapesUsingEncoding:, y sustituyen los caracteres especiales de las URLs por sus equivalentes “escapados” usando porcentajes, como por ejemplo el símbolo del $ la convertirá en %24.

Pero sin embargo no hay ninguna función para transformar las entidades en sus caracteres equivalentes.

La primera solución que se nos puede ocurrir es usar el mensaje stringByReplacingOccurrencesOfString:withString: por cada entidad. Y aunque funciona, es bastante penalizador desde el punto de vista del rendimiento, ya que si tenemos el siguiente código.

NSString* cad = [NSString stringWithString:@"&lt;&apos;&amp;&apos;&gt;"];
	NSLog(@"%@", [[[[cad stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"]
				  stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"]
				  stringByReplacingOccurrencesOfString:@"&amp;" withString:@"&"]
				  stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"]);

Recorrerá la cadena entera tantas veces como entidades queramos sustituir, lo que para cadenas largas puede ser un gasto bastante grande e innecesario.

Después de buscar por internet, no encontré nada que me convenciera, asi que tome el camino del medio, y hice una categoria de NSString, que recorre la cadena y sustituye las ocurrencias, de las entidades por sus caracteres.

Al ser una categoria, no hace falta mas que incluir el fichero .h y llamarlo sobre cualquier objeto NSString.

@interface NSString (RemoveHtmlEntities)

- (NSString*) stringByRemovingHtmlEntities;

@end

@implementation NSString (RemoveHtmlEntities)

- (NSString*) stringByRemovingHtmlEntities {
	NSMutableString* newStr = [[NSMutableString alloc] init];
	NSUInteger i = 0;
	unichar c = 0;
	NSUInteger strLen = [self length];
	while (i < strLen) {
		c = [self characterAtIndex:i];
		if ( c == '&' ) {
			if ( [self rangeOfString:@"amp;" options:NSCaseInsensitiveSearch range:NSMakeRange(i, (5>(strLen-i))?strLen-i:5)].location != NSNotFound ) {
				[newStr appendFormat:@"&"];
				i += 5;
			} else if ([self rangeOfString:@"lt;" options:NSCaseInsensitiveSearch range:NSMakeRange(i, (4>(strLen-i))?strLen-i:4)].location != NSNotFound) {
				[newStr appendFormat:@"<"];
				i += 4;
			} else if ([self rangeOfString:@"gt;" options:NSCaseInsensitiveSearch range:NSMakeRange(i, (4>(strLen-i))?strLen-i:4)].location != NSNotFound) {
				[newStr appendFormat:@">"];
				i += 4;
			} else if ([self rangeOfString:@"quot;" options:NSCaseInsensitiveSearch range:NSMakeRange(i, (6>(strLen-i))?strLen-i:6)].location != NSNotFound) {
				[newStr appendFormat:@"\""];
				i += 6;
			} else if ([self rangeOfString:@"apos;" options:NSCaseInsensitiveSearch range:NSMakeRange(i, (6>(strLen-i))?strLen-i:6)].location != NSNotFound) {
				[newStr appendFormat:@"'"];
				i += 6;
			} else {
				[newStr appendFormat:@"&"];
				i++;
			}
		} else {
			[newStr appendFormat:@"%c", c];
			i++;
		}
	}
	return [newStr autorelease];
}

@end

Como veis, solo transforma las entidades que necesitaba en el momento de desarrollo, pero es trivial añadir mas clausulas “else if” al código 😉

Un posible uso del código sería

	NSString* cad = [NSString stringWithString:@"&lt;&apos;&amp;&apos;&gt;"];
        NSLog(@"%@", [cad stringByRemovingHtmlEntities]); 
       // Imprime <'&'>

Métodos privados en Objetive-C

julio 25, 2010

Si programamos habitualmente en Objetive-C seguramente nos habremos encontrado con la necesidad de crear un método que sea solo accesible desde dentro de la clase, vamos, un método privado 🙂

Seguramente, en este momento recordemos como se hace en otros lenguajes, pero no podemos recordar como se hacia en este lenguaje. El motivo de esta falta de recuerdo es por que realmente no nos habremos encontrado una sección sobre ello en el libro o web que usamos para aprender este lenguaje.

Si bien existe la habituales directivas de ámbito @private, @public y @protected de compilador, solo tienen aplicación en los atributos de la clase, y no en los métodos. Además al igual que pasa con otros lenguajes estas directivas solo se aplican en el compilador, pero en el caso de Objetive-C, si accedemos a estas variables privadas, solo obtendremos un warning, como el que vemos en la imagen.

Pero entonces ¿como definimos métodos privados?. Antes de ello vamos a repasar que contiene un fichero de implementación.

Los ficheros .m habitualmente contienen la definición de los métodos que se han declarado en el fichero .h. Como seguramente sabremos, dichas definiciones están comprendidas entre las directivas @implementation CLASE y @end. ¿Que pasa si intentamos definir un método fuera de este bloque?. Pues depende ;), si intentamos definir un método de la clase, el compilador no nos dejara, pero si por otro lado tratamos de definir una función de C o C++, el compilador no pondrá ningún problema. De esta manera podemos pensar que la sección entre @implementation y @end es la parte Objetive-C del fichero .m. Fuera de esta sección no podremos acceder a cosas como “self”, aunque si podremos meter sin problemas código en Objetive-C. Por ejemplo, veamos el contenido del siguiente fichero .m.

int sumaC(int a, int b) {
	PruebaPrivado *pp = [[PruebaPrivado alloc] init];
	return [pp suma:a with:b];
}

@implementation PruebaPrivado
-(int) suma: (int) op1 with: (int) op2 {
	return op1 + op2;
}

-(int) suma2: (int) op1 with: (int) op2 {
	return sumaC(op1, op2);
}

@end

En Objetive-C se sigue una filosofía parecida. La primera aproximación de método privado pasa por declarar esa función únicamente en el fichero .m, y no en el .h. De esta manera los clientes de la clase importarán en fichero .h, y no sabrán de la existencia de los métodos privados. Eso si, como hemos visto, si queremos acceder al contenido de la clase, debe estar definida dentro del bloque de implementación. Como podemos ver en el siguiente ejemplo.

@implementation PruebaPrivado

-(int) suma: (int) op1 with: (int) op2 {
	return [self sumaPrivada: op1 with: op2];
}

-(int) sumaPrivada: (int)o1 with: (int) o2 {
	return o1 + o2;
}

@end

Sin embargo, esta forma de hacerlo tiene sus inconvenientes, por un lado, si compilamos el código del ejemplo el compilador nos dará un warning. Este warning viene de que sumaPrivada no esta definido en el momento de compilar el método suma. Por lo que el compilador nos informa de que PruebaPrivado puede no responder al mensaje sumaPrivada. Este warning se solucionaría poniendo la declaración del método antes de su uso, como pasa habitualmente con C.

Pero aún sin el warning, otro principal inconveniente es la legibilidad. Si intercalamos métodos privados con públicos, mas adelante puede ser un follón revisar nuestro propio código, ya que no tendremos agrupadas todas las funciones privadas de nuestra clase.

Aunque las solución anterior presentaba ciertos inconvenientes, sienta las bases de la solución que habitualmente se suele usar. Con la incorporación de las categorías en Objetive-C se abre la posibilidad de modificar una clase “a posteriori” como ya vimos en esta otra entrada.

La solución pasa por crear una categoría en el fichero .m de implementación, que no estará visible por ningún cliente y que agrupara los métodos privados, de esta manera todos los métodos estarán declarados en el mismo lugar, y nos quitaremos tanto el problema del warning del compilador como la desorganización.

Por tanto, el código quedara como:

@interface PruebaPrivado ()

-(int) sumaPrivada:(int)o1 with:(int)o2;

@end


@implementation PruebaPrivado

-(int) suma: (int) op1 with: (int) op2 {
	return [self sumaPrivada: op1 with: op2];
}

-(int) sumaPrivada: (int)o1 with: (int) o2 {
	return o1 + o2;
}

@end

Como vemos, ahora sumaPrivada esta declarada dentro de la categoría, que además como habéis visto, no lleva nombre. Este hecho nos aporta alguna ventaja como es que la definición de los métodos puede ir en la misma sección de implementación que los métodos públicos, en lugar de tener que crear una sección especifica para esta categoría.


Key-Value coding

julio 17, 2010

Seguramente en muchos de vuestros desarrollos os habreis encontrado con las típicas clases que contienen únicamente datos. Por ejemplo, en Java estas clases se llaman POJOs. Normalmente la forma de acceder al contenido de estos datos es usando los métodos de acceso, también llamados getters y setters.

El Key-Value coding (KVC), nos va a permitir acceder a estos datos de forma un poco diferente, y en cierta manera, mucho mas útil y dinámica.

El uso típico de lenguajes como Java o C# es utilizar unicamente los métodos de acceso, sin embargo en otros entornos como los lenguajes de script, se nos abren otras posibilidades para acceder a los datos que encapsula una clase. Con los ultimos cambios que se incorporaron a Objetive-C, el mecanismo para acceder a dichos datos, está mas cerca de los lenguajes de script que de los lenguajes compilados tradicionales.

Gracias a KVC podremos acceder a las variables usando únicamente su nombre, de tal manera que el propio runtime se encargará de llamar a los métodos de acceso adecuados. La forma de acceder a estas variables es usando un par de métodos genericos, getValueForKey: y setValue:forKey:.

La pregunta es. ¿Y para que necesitamos hacer esto de esta manera en lugar de usar los tipicos getters y setters?. Para responderla imaginemonos la siguiente situación, tenemos un conjunto de nombres de propiedades almacenados en un array, si queremos acceder a las propiedades usando los nombres, con estos métodos el acceso sería directo, sin embargo, con el acceso tradicional deberiamos “montar” un conjunto de ifs para analizar cada caso. En código sería algo así:

/* SIN KVC */
// array tiene ["altura", "peso", "edad"]
for (NSString* prop in array) {
	if ( [prop isEqual:@"altura"] ) {
		valor = [persona altura];
		NSLog(@"El valor de altura para la persona es %f", valor);
	} else if ( [prop isEqual:@"peso"] ) {
		valor = [persona peso];
		NSLog(@"El valor de peso para la persona es %f", valor);
	} else if ( [prop isEqual:@"edad"] ) {
		valor = [persona edad];
		NSLog(@"El valor de edad para la persona es %f", valor);
	}
}

/* CON KVC */
for (NSString* prop in array) {
	valor = [persona getValueForKey:prop];
	NSLog(@"El valor de %@ para la persona es: %f", prop, valor);
}

Hablando de un caso práctico, el tipico ejemplo es para rellenar los datos de una tabla, el método encargado de devolver el valor de una columna obtiene el nombre de dicha columna, que habitualmente se corresponde con una propiedad de una clase, usando KVC, el método puede devolver el valor de la propiedad de forma directa. Como vemos en el siguiente fragmento de código

- (id)tableView:(NSTableView *)tableview 
  objectValueForTableColumn:(id) theColumn
                        row:(int) theRow
{
    Persona *p = [arrayPersonas objectAtIndex:theRow];
	return [p valueForKey:[theColumn identifier]];
}

De hecho, este mecanismo de acceso a propiedades es el que se utiliza cuando realizamos un binding en el Interface Builder. Automaticamente liga el valor del control a la propia propiedad del objeto, de tal manera que hacer que una vista muestre el contenido de una clase es bastante trivial.

Y, ¿Cómo hago que mi clase soporte los mecanismos KVC?. Para responder a la pregunta, primero vamos a ver como funciona internamente los mecanismos de KVC. 😉

Cuando enviamos el mensaje getValueForKey: o setValue:forKey:, internamente se busca la existencia de un método de acceso que use la nomenclatura estandar, si por ejemplo, la key es “peso”, se buscará un par de métodos llamados “peso” y “setPeso”. Si existen, se usarían para acceder a los datos. En el caso de que no existan, se envía el mensaje accessInstanceVariablesDirectly, si este mensaje retorna “YES”, se procede a buscar la propia variable dentro del objeto. Si este procedimiento tampoco funciona, entonces se le envía al objeto el mensaje setValue:forUndefinedKey: como última instancia. La implementación por defecto de este método levanta una excepción. Pero el objeto puede sobrecargar esta implementación por defecto para provocar otro comportamiento. Realmente el proceso de acceso para un “get” es algo mas complejo que el que hemos expuesto, pero a grandes rasgos se podría simplificar como en el caso de los “set”

Volviendo a la pregunta, para que nuestra clase soporte el acceso KVC, la forma mas sencilla es proporcionar los métodos estandar. Para realizar esta tarea, tenemos varias opciones. Una de ellas, y las obvia, es hacernos nosotros a mano estos métodos, sin embargo, Objetive-C nos brinda la posibilidad de autogenerar este código.

En esta autogeneración entra en juego dos elementos, @property y @synthesize . @property nos servirá para declarar las propiedades en el fichero .h, mientras que @synthesize nos servirá para definir los métodos de acceso dentro de la sección de implementación. Por ejemplo:

// Persona.h
@interface Persona : NSObject {
}

@property (retain) NSNumber* peso;
@property (retain) NSNumber* altura;
@property (retain) NSNumber* edad;

@end

// Persona.m
@implementation Persona
@synthesize peso, altura, edad;

@end

Únicamente colocando ese código, el compilador generará por nosotros los métodos de acceso. Sin embargo, si necesitamos un procesamiento especial en el acceso a los datos de nuestra clase, tendremos que manualmente, implementar dichos getters y setters.

Seguramente os habreís fijado en el (retain) que esta incluido en la declaración de la propiedad. Lo que colocamos entre parentesis son los atributos de la propiedad e indica que se va a hacer la asignación de la propiedad. El tema es algo complejo y podría ser una entrada en el blog, por lo que de momento, nos podemos quedar en que existen tres tipos exclusivos entre si, retain, assign y copy. Y que hacen un retain sobre la variable, la asignan tal cual o la copian respectivamente.

Muy ligado a todo lo que hemos hablado, esta el acceso “simplificado” a estos campos que se introdujo recientemente en Objetive-C. Este acceso se conoce como “dot syntax”. Usando esta técnica podemos acceder a los datos simplemente poniendo un “.” entre la instancia que posee los datos y el nombre del dato, como por ejemplo:

persona.peso = [NSNumber numberWithInt:5];
NSLog(@"El peso es: %@", persona.peso);

Al igual que lo que hemos comentado antes, este acceso realmente esta enmascarando una llamada a setPeso: y peso, de la clase Persona.

Como veis, estos mecanismos simplifican el código, y aprovechandose del dinamismo de Objetive-C, proporcionan cosas tan importantes como son los bindings.


Closures en C y Objective-C

junio 30, 2010

Si, aunque intenteis leer otra vez el título del post, vamos a hablar de, las tan de moda, closures para C. 🙂

Sin duda, dada la naturaleza de C, se hace extraño que se añadan funcionalidades que normalmente se asocian a lenguajes mas modernos (o aún en evolución) como C#, Java o otros lenguajes de script como Python o Ruby

El nombre elegido para referirnos es “blocks”, y básicamente ha sido un añadido de Apple al compilador GCC que usamos en Mac y al futuro CLang que corre sobre el también futuro y prometedor LLVM.

Por el momento esta extensión de C no es estandar, y dada la cerrada naturaleza de los estándares de C es complicado que llegue a serlo. Pero, por otro lado, al estar implementado en compiladores como GCC o en el frontend de LLVM Clang, y además, al ser estos compiladores opensource y portables entre diferentes plataformas, presumiblemente esta extensión se pueda utilizar sin problemas en el futuro, al igual que usamos ciertas extensiones propias de GCC que tampoco forman parte de los estandares de C.

Apple desarrolló los blocks como parte de la tecnologia “Grand Central Dispatch”. Esta tecnologia optimiza ciertos bloques de ejecución, y como podeis esperar, el “empaquetar” los bloques de ejecución usando esta extensión del lenguaje facilita mucho la gestión por parte del sistema operativo y la programación por parte de los desarrolladores.

Hasta ahora hemos estado hablando alegremente de closures, básicamente los closures es una forma de encapsular un comportamiento bajo una variable. Usando esta variable podemos manejar el comportamiento (o función) de la misma manera que manejamos el resto de variables, esto es, por ejemplo, pasarlo como parámetros a una función.

Como siempre, lo mejor es verlo con un ejemplo, antes de adentrarnos en C,vamos a ver un ejemplo en Javascript. Lo bueno de este lenguaje es que la sintaxis es muy sencilla y nos va a permitir ver el concepto mas fácilmente.

funcion_suma = function(a,b) { return a+b; }
funcion_resta = function(a,b) { return a-b; }

function opera(op1, op2, operacion) {
	return operacion(op1, op2);
}

opera(3, 2, funcion_suma);
  // Imprime 5
opera(3, 2, funcion_resta);
  // Imprime 1
opera(3, 2, function(a,b) {
	return a*b;
});
  // Imprime 6

En el ejemplo creamos dos variables asignadas a funciones, que realizan las diferentes operaciones, y estas variables se las pasamos a la funcion “opera”. Cuando desarrollamos la funcion “opera” no sabemos que operación vamos a realizar, dejamos esa puerta abierta para que cada cliente de la función aporte su propia función de operación. Como vemos en el último caso, podemos definir la propia función cuando construimos los parámetros de la llamada.

La gran ventaja de esta técnica es la extensibilidad, ya que dejamos total libertad para que el desarrollador aporte la función a la que se va a llamar. Este ejemplo es muy sencillo, pero al final del post veremos puntos de Cocoa donde se estan usando los blocks y veremos de forma mas clara en que son una ventaja.

Centrandonos ya en C, Apple ha escogido el simbolo ^ para marcar un bloque. Es curioso ya que este simbolo se utilizaba en otra extension de C++ por parte de Microsoft para marcar cierto tipo de variables cuando se desarrolla con Managed C++.

Por lo tanto, para definir un bloque en C, usamos el simbolo ^, seguido de la lista de parámetros entre parentesis y después el bloque de codigo que conforma el bloque. Para definir el tipo del bloque usamos el tipo de retorno, el nombre del bloque entre parentesis y precedido de ^ y finalmente la lista de parámetros entre parentesis. Aunque pensandolo bien todo este parrafo me lo podría haber ahorrado, simplemente poniendo un ejemplo 😉

int (^funcion_suma)(int, int) = ^(int a, int b) { return a + b; };

Siguiendo la linea anterior, esta sería la forma de declarar una variable de tipo “funcion_suma” al igual que haciamos en javascript. Como vemos, la sintaxis es realmente mas compleja que la de javascript.

int opera(int op1, int op2, int (^funcion_opera)(int, int)) { return funcion_opera(op1, op2); }

opera(3, 2, funcion_suma);
  // Imprime 5
opera(3, 2, ^(int a, int b) {
	return a * b;
})
  // Imprime 6

Y aquí tenemos la anterior versión de la función “opera” pero en C, como vemos el concepto es similar, pero con una sintaxis mas enrevesada.

Si habeis programado en otros lenguajes como Java, la ultima invocación os sonara a clases anonimas, y ciertamente se les parece bastante. Al igual que con estas clases los blocks tienen suelen ser un buen sustituto a la hora de crear un callback. Una ventaja con respecto a la forma tradicional de implementar dichos mecanismos, es que pueden acceder a las variables locales del entorno donde se estan ejecutando. Esto es bastante util en numerosas ocasiones, usando blocks nos ahorraremos tener que pasar dichos datos a la funcion u objeto que implemente el callback.

Para marcar que una variable va a ser accedida dentro de un bloque, usamos el modificador __block antes de la variable que va a ser accedida dentro del bloque. Como por ejemplo:


__block int multiplicador = 6;

opera(3, 2, ^(int a, int b) {
	return a * b * multiplicador;
})
  // Imprime 36;

A partir de iOS 4 en el iPhone y OSX 10.6 los bloques son una realidad en Cocoa y Cocoa Touch. Poco a poco van apareciendo métodos que soportan un bloque para indicar el comportamiento de una acción.

Un ejemplo, sacado de la documentación de apple es método sortedArrayUsingComparator: del NSArray. El uso tradicional de este funcionalidad seria pasandole un puntero a función que resuelva la comparación, como podemos ver en sortedArrayUsingFunction:context:. Como hemos visto anteriormente, dada a la limitación de este método, Cocoa nos proporciona un puntero a nuestros datos, reflejado en el parámetro context.

Si usamos bloques en este caso, nos saltamos esta limitación, y además, facilita la lectura del código ya que podemos poner la lógica del comparador en la misma llamada de la función.

Para finalizar el post, vamos a ver un ejemplo de una ordenación de un Array usando bloques y sin usarlos

Usando el método tradicional, la ordenación del array quedaría algo como:

NSInteger alphaComparator(id arg1, id arg2, void* arg3) {
  NSString *a = (NSString*)arg1;
  NSString *b = (NSString*)arg2;
  return strcmp([a cStringUsingEncoding:[NSString defaultCStringEncoding]],
				[b cStringUsingEncoding:[NSString defaultCStringEncoding]]);
}

int main (int argc, const char * argv[]) {
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

  NSArray *stringsArray = [NSArray arrayWithObjects:
    @"Roberto",
	@"Alfonso",
	@"Ruben",
	@"Mariano",
    @"Juan",
	@"Antonio",nil];

  NSArray* sortedArray = [stringsArray
			sortedArrayUsingFunction:alphaComparator context:nil];
  for ( NSString* cad in sortedArray ) {
    NSLog(@"%@\n", cad);
  }

  return 0;
}

Por otro lado, usando bloques quedaría algo como:

iint main (int argc, const char * argv[]) {

  NSArray *stringsArray = [NSArray arrayWithObjects:
   @"Roberto",
   @"Alfonso",
   @"Ruben",
   @"Mariano",
   @"Juan",
   @"Antonio",nil];

  NSArray* sortedArray = [stringsArray sortedArrayUsingComparator:^(id str1, id str2) {
    NSString *a = (NSString*)str1;
	NSString *b = (NSString*)str2;
	return (NSComparisonResult)
			strcmp([a cStringUsingEncoding:[NSString defaultCStringEncoding]],
				  [b cStringUsingEncoding:[NSString defaultCStringEncoding]]);
  }];

  for ( NSString* cad in sortedArray ) {
	NSLog(@"%@\n", cad);
  }

  return 0;
}

Sin duda, bajo mi punto de vista la solución usando bloques es mucho mas elegante, pese a que el enfrentamiento inicial con los blocks pueda ser algo “dura” 😀

Como conclusión, simplemente decir que es muy grato ver como se van añadiendo funcionalidades a nuestro lenguaje favorito y, de esta manera, adaptandolo un poco mas a los tiempos en los que vivimos 🙂


Medidor de luz en Cocoa usando Arduino

junio 8, 2010

Hace tiempo que no publicaba nada del magnífico Arduino. La culpa, como siempre, de que los días sólo tengan 24 horas 😉

En el anterior post sobre Arduino, presentamos lo fácil que era conectar processing con Arduino. En este post vamos a ver que no sólo con Processing, realmente leer los datos que nos da el Arduino es fácil desde cualquier sitio.

Para presentarlo vamos a mostrar un pequeño programa hecho en Cocoa que lee los datos recogidos por el Arduino y lo muestra gráficamente.

En primer lugar pondremos el esquema del circuito.

El circuito es bastante sencillo y sin muchos secretos, el único detalle a tener en cuenta es que utilizamos una resistencia pull-up de 1KOhm para medir la tensión después del sensor LDR. Esto lo conectamos a la entrada 0 de la placa del Arduino.

De esta manera el arduino leerá el valor de esa entrada, pero necesitamos alguna manera para comunicarnos con el PC. Aquí es donde entra la sencillez del Arduino, ya que podemos usar el puerto USB para comunicarnos. Los datos los enviaremos con la librería Serial. Desde el PC, al tratarse de una comunicación serie, podemos usar cualquier mecanismo para leer del puerto. Y cuando decimos cualquiera, realmente hay un mundo de posibilidades, por mencionar algunos, tenemos librerias en Python, Java o incluso usando la librería estandar de C.

El código del programa que cargamos en el arduino es el siguiente

int LDR = 0;
int val = 0;
int delayTime = 500;

void setup()
{
  pinMode(LDR, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  val = analogRead(LDR);
  Serial.println(val);
  val = 0;
  delay(delayTime);
}

Como vemos es bastante sencillo. En el Setup, configuramos el puerto serie con una velocidad de 9600 baudios y cada lectura la escribimos en el puerto serie usando el Serial.write.

De la misma manera podemos usar el puerto USB para establecer la comunicación inversa, en algun futuro post veremos como realizarla, y como usar el Arduino como medio para mostrar información de forma diferente.

Cuando instalamos el driver de Arduino en nuestro PC, nos crea un dispositivo que variará segun el sistema operativo. En mi caso, OSX, el dispositivo es /dev/tty.usbserial-A900aeKy , por lo que con el programa cargado, podremos leer de ese puerto los datos que esta leyendo la placa del sensor. Para ello podemos usar el programa screen, que viene con la gran mayoría de sistemas basados en UNIX.

Si ejecutamos en una terminal el comando

$ screen /dev/tty.usbserial-A900aeKy

Deberíamos ver algo parecido a esto:

En pantalla podemos ver como van apareciendo los valores que esta leyendo la placa, si variamos la intensidad de la luz, efectivamente vemos como dichos valores cambian.

Una vez que tenemos lista la parte del Arduino, la siguiente parte es crear la aplicación en PC. Como hemos mencionado antes, para capturar los datos que nos llegan, debemos leer del puerto serie. Para ello, y al estar en un sistema Unix, podemos utilizar la Api estándar para leer de un dispositivo.

Como esto lo vamos a usar desde una aplicación en Cocoa, vamos a encapsular estas funciones en un objeto de cocoa, de tal manera que su uso sea mas sencillo. Este objeto al construirse abrirá el puerto serie, y nos ofrecerá un método para obtener el siguiente valor leído.

Hablando del código en C, como podeis suponer no tiene mucho secreto, usando open() abriremos el fichero que representa el dispositivo, y con read() leeremos los datos.

El enlace al código fuente esta al final de la entrada, pero el código principal que realiza esto es algo como lo siguiente:

int fd = open("/dev/tty.usbserial-A900aeKy", O_RDWR | O_NOCTTY | O_NDELAY);
char buffer[100]; memset(buffer, 0, 100);
int nbytes = read(fd, buffer, 100);

La última parte que nos falta del puzzle es la aplicación Cocoa que se encargará de mostrar los datos, la idea es mostrar un numero que indique el valor leido del sensor, y un medidor del tipo NSLevelIndicator para mostrar un indicador gráfico del valor del sensor.

No entraré en detalle en comentar la aplicación en Cocoa ya que es muy sencilla, la aplicación consta de una Custom View que pinta el número leido. Para realizar las lecturas periodicas, se utiliza un NSTimer que llamará periodicamente a un método que le especifiquemos y que se encargará de actualizar la vista con el nuevo dato leido.

Para finalizar el post, os dejo con un video del programa en funcionamiento y el código de la aplicacion Cocoa y del programa de Arduino.

Codigo Fuente


Cargando dinámicamente una clase

mayo 25, 2010

Siguiendo un poco con el tema del anterior post, en esta entrada vamos a ver como podemos cargar una clase de forma dinámica usando principalmente NSClassFromString.

Gracias a este mecanismo, podemos dejar para la ejecución la elección de la clase que vamos finalmente vamos a utilizar. Esto es bastante útil cuando estamos desarrollando, por ejemplo, un sistema de plugins, de tal manera que en tiempo de ejecución se cargará la clase que contiene el código del plugin. Cosa que en tiempo de compilación no conocemos.

Este mecanismo hace uso intensivo de dos funcionalidades de Objetive-C.

Una de ellas es la capacidad para mandar mensajes a los objetos sin que estos tengan que estar definidos previamente, que es precisamente lo que vimos en el anterior post, por lo que no entraré en mas detalles.

La otra caracteristica que es usada por la carga dinámica de clases es los tipos anónimos. Dichos tipos pueden contener cualquier tipo de instancia de clase. A priori podríamos caer en error de confundirlo con el void* de C/C++, sin embargo aunque comparte la caracteristica de “tipo genérico”, las implicaciones que hay detras del tipo anónimo de Objetive-C son más profundas.

El tipo anónimo se representa por la palabra clave “id“. Cuando declaramos una variable de tipo id, podemos enviarle cualquier mensaje, y si la instancia que hay detras de ese tipo es capaz de responder al mensaje, lo responderá. Ahondando en las diferencias con el void* de C++, usando id, no necesitamos hacer ningun cast para invocar a sus métodos. Lo cual aporta mucha seguridad a nuestro código, porque, como ya sabremos, se podría decir que los cast son de los mecanismos mas inseguros a la hora de desarrollar.

// C++
int myfunc(void* obj1)
{
    obj1->metodo1(); // !!!!! ERROR de compilación
    ((MiClase)obj1)-&gt;metodo1();
        // OK, pero si obj1 no es de tipo MiClase fallará al ejecutarse.
        // Bastante inseguro
}

// Obj-C
- (int) myfunc:(id) obj1
{
    [obj1 metodo1];
        // Compila perfectamente, si en tiempo de ejecucion obj1 no responde al mensaje metodo1.
        // no pasa nada grave excepto que no retorna nada. No es nada inseguro.
}

Como podemos intuir, el tipo id nos viene perfectamente “al pelo” para entender el funcionamiento de NSClassFromString(). Este método nos va a devolver un objeto de tipo Class que contiene la definición de la clase, cuando instanciamos esta clase el tipo que nos permite referenciar la instancia es “id“.
Realmente no sabemos de que tipo es, de hecho, gracias a la “magia” de Objetive-C no necesitamos tener ni el .h de la clase que estamos instanciando.

Este mecanismo existe sin duda en otros lenguajes como C/C++ o Java. Normalmente para hacer esto es requerido que la clase que estamos instanciando implemente alguna interfaz, de tal manera que referenciaremos a la instancia usando la propia interfaz. En objetive-C tambien podemos hacer esto, pero mientras que en los otros lenguajes es necesario, aquí, no lo es.

Para demostrar el funcionamiento vamos a ver un ejemplo. Tenemos dos clases que realizan una operación. Dichas clases son Adder y Substractor, como se puede adivinar, la operación de uno es la suma y la resta es la del otro.

@interface Adder : NSObject {
}
- (int) operate:(int) op1 with:(int) op2;
@end

@implementation Adder
- (int) operate:(int)op1 with:(int)op2 {
    return op1 + op2;
}
@end

@interface Substractor : NSObject {
}
- (int) operate:(int) op1 with:(int) op2;
@end

@implementation Substractor

- (int) operate:(int)op1 with:(int)op2 {
    return op1 - op2;
}
@end

La idea es que, en nuestro programa pidamos al usuario el nombre de la clase a cargar, y dinámicamente carguemos la clase y llamemos a su método “operate”

int main (int argc, const char * argv[]) {
    char buffer[300]; memset(buffer, 0, 300);
    fgets(buffer, 300, stdin);
    buffer[strlen(buffer)-1] = 0; // Quitamos el salto de linea

    NSString* classString = [NSString stringWithCString:buffer encoding:NSASCIIStringEncoding];
    int op1 = 5, op2 = 4;
    Class cl = NSClassFromString(classString);
    if ( cl != nil ) {
        id ad = [[cl alloc] init];
        printf("Operating %d with %d. Result: %d", op1, op2, [ad operate:op1 with:op2]);
    }
    else {
        printf("Error loading class");
    }
}

El resultado es el que esperamos, si tecleamos Adder se realizará una suma y si tecleamos Substractor se restarán ambos números.

Este ejemplo es bastante sencillo pero creo que ilustra el funcionamiento de la carga dinámica de clases. En Cocoa este mecanismo se utiliza bastante frecuentemente, por ejemplo la clase NSApplication lo utiliza para instanciar nuestra aplicación.