Construyendo un Servicio en OSX

Uno de los aspectos que pasan mas desapercibidos en OSX son los “Servicios”. Seguramente por el nombre pensareis que es un programa que se ejecuta de fondo en nuestro ordenador.

Si bien ese pensamiento no es del todo incorrecto, los servicios en OSX es algo mas. Con servicios me refiero a los elementos del menú que sale cuando pinchamos sobre el nombre del programa activo en la barra de menús.

La localización de dicho menú ha ido cambiando con el tiempo, en versiones anteriores ocupaban una posición mas destacada, pero poco a poco han ido pasando a un plano mas “oculto”.

Sin embargo, la posición de esta funcionalidad no nos tiene que despistar, ya que la utilidad que prestan es bastante buena.

Para comprobar su funcionamiento, solo tenemos que seleccionar algo de texto, e ir al menú Servicios. Desde dicho menú se nos dará la opción de hacer diversas cosas, como por ejemplo, crear una nota. Además no solo los servicios están accesibles desde este menú, si no que podremos acceder usando atajos de teclado. Por ejemplo, si pulsamos SHIFT+ ⌘+Y, crearemos la nota al instante.

Una de las grandes ventajas de los servicios es que están disponibles para todo el sistema, esto es, independientemente de la aplicación donde seleccionemos el texto, si pulsamos el atajo de teclado, crearemos una nota con el texto seleccionado.

Como podemos leer en la propia documentación de Apple, posibles servicios serian, reconocedores de texto en una imagen, cifrado de texto o incluso, aunque no venga en la guía de Apple, sería útil un servicio para insertar una cita de Chuck Norris en el documento actual🙂

Desde el punto de vista de la programación, se pueden distinguir dos elementos, por un lado el propio servicio, y por otro la aplicación que interactua con él. La pieza que intercomunica ambas partes es el clipboard. Cuando pinchamos en un servicio, la aplicación pone los datos necesarios en el clipboard, e invoca al servicio. El servicio por su parte, recoge dichos datos, los procesa y los vuelve a poner en el clipboard. Finalmente, la aplicación recoge lo que haya en el clipboard y hace lo que considere oportuno con dichos datos.

En la entrada vamos a crear un servicio, que seleccionado texto, lo consulte en la wikipedia usando Safari.

El código que atiende al servicio, es sencillo, a grandes rasgos, los pasos que hay que dar son por un lado, crear el método al que se llamará, y por otro, registrar el servicio en el sistema.

Desafortunadamente, xcode no tiene plantillas para crear los servicios, por lo que tendremos que empezar desde un proyecto vacío que cree un ejecutable.

Una vez que tenemos el proyecto creado en el XCode, debemos añadir (si no lo estaba antes), el framework de Cocoa y Foundation, y añadir la clase que implementará el método que atiende el servicio.

En nuestro caso, dicha clase es WikipediaService


==== WikipediaService.h

#import <Cocoa/Cocoa.h>


@interface WikipediaService : NSObject {

}

- (void) wikipediaSearch: (NSPasteboard*) pboard 
				userData:(NSString*) theUserData 
				   error:(NSString**) theError;

@end

==== WikipediaService.m

@implementation WikipediaService

- (void) wikipediaSearch: (NSPasteboard*) pboard userData:(NSString*) theUserData error:(NSString**) theError
{
	// Test for strings on the pasteboard.
	NSArray *classes = [NSArray arrayWithObject:[NSString class]];
	NSDictionary *options = [NSDictionary dictionary];
	
	if (![pboard canReadObjectForClasses:classes options:options]) {
		*theError = NSLocalizedString(@"Error recuperando datos del pboard", 
									  @"pboard couldn't give string.");
		return;
	}
	
	// Get and encrypt the string.
	NSString *pboardString = [pboard stringForType:NSPasteboardTypeString];
	NSString *wikipediaString = [NSString stringWithFormat:@"http://en.wikipedia.org/wiki/%@", pboardString];
	NSURL *url = [[NSURL alloc] initWithString: wikipediaString];
	[[NSWorkspace sharedWorkspace] openURL:url];
	
	[pboard clearContents];
}

@end

Como vemos, el clipboard es la parte que comunica ambos procesos. Con el mensaje canReadObjectForClasses primero comprobamos si el clipboard contiene datos de tipo cadena, y luego con el mensaje stringForType del “pasteboard” obtenemos dicha cadena.

Por otro lado, en nuestro punto de entrada de la aplicación, debemos situar el código que registra el servicio en el sistema.

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

	NSRegisterServicesProvider([WikipediaService new], @"WikipediaService");
	NSUpdateDynamicServices();
	[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
	return 0;
}

Antes de ejecutar y probar nuestro servicio, nos queda una parte muy importante. En el fichero plist de la aplicación, debemos indicar los datos referentes al servicio. Que indicará al sistema como llamar y como mostrar la información asociada.

	<key>NSServices</key>
	<array>
		<dict>
			<key>NSMenuItem</key>
			<dict>
				<key>default</key>
				<string>Wikipedia Search</string>
			</dict>
			
			<key>NSKeyEquivalent</key>
            <dict>
                <key>default</key>
                <string>R</string>
            </dict>
			
			<key>NSMessage</key>
			<string>wikipediaSearch</string>
			
			<key>NSPortName</key>
			<string>WikipediaService</string>
			
			<key>NSSendTypes</key>
			<array>
				<string>NSStringPboardType</string>
				<string>NSPasteboardTypeString</string>
			</array>			
		</dict>
	</array>

Si os fijáis, en el campo, NSKeyEquivalent, podemos asignar una tecla, que sumada a Command, sera el shortcut para llamar a nuestro servicio. Si dicha letra esta en mayúsculas, ademas necesitaremos pulsar Shift.

Con todo ya terminado, solo nos queda instalarlo, para ello debemos copiar el “Bundle” que ha generado nuestro proyecto en XCode a ~/Library/Services. Para que el servicio sea reconocido, debemos cerrar sesion y volverla a inciar, pero existe una forma manual para forzar al sistema para que reconstruya el indice de servicios.

Esto es ejecutando el siguiente comando: /System/Library/CoreServices/pbs

Una vez que tenemos nuestro servicio instalado, solo tenemos que seleccionar cualquier texto para buscarlo en la wikipedia.

Una respuesta a Construyendo un Servicio en OSX

  1. Tyflos dice:

    Hola, otro magnífico artículo. Tengo una duda, podemos hacer un servicio que responda a varios atajos de teclado? por ejemplo: si pulsamos blockMayus+flecha izquierda hace una cosa y si pulsamos blockMayus+flecha derecha hace otra cosa. Supongo que el usar la tecla comand es obligatorio así que sería pulsando comando+mayúsculas+flecha izquierda y comando+mayúsculas+flecha derecha

    Gracias

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: