Ser programador es una inagotable fuente de alegrías, más cuando eres una orquesta de un único hombre. Cuando no falla tu código, falla el servidor, cuando no es la pasarela de pago, si no es que se te ha caído el servidor de correo y no se envían los números de serie.
Eso sin olvidar que a veces las actualizaciones del sistema cambian el comportamiento de algunas APIs, obviamente sin documentarlo, que a veces, sin saber por qué, lo que acabas de compilar sin errores hace dos minutos decide no compilar hasta dentro de un par de horas, también si saber por qué… en fin, que el asunto es una fuente inagotable de alegrías.
Un ejemplo de estas tonterías que pasan a veces, es el siguiente que paso a narrar.
Ayer publiqué Quiet Read, una aplicación de esas a las que casi puedes mandar a la compra de lo bien hechas que están. Pero a lo que iba: se supone que se deben arrastrar links desde el navegador al icono de la aplicación en la menu bar. En ese momento, la aplicación intenta adivinar si lo que se está arrastrando sobre ella es un link o no, para aceptar o rechazar el drop.
El asunto no tiene mucha complicación: en el momento en el que se recibe la referencia a un pasteboard se extrae el primero de sus contenidos:
NSPasteboardItem *item = [ [ pb pasteboardItems ] objectAtIndex: 0 ];
Cuando el link viene de Safari, que es mi navegador por defecto, y por tanto, el único en el que probé la aplicación (mea culpa, lo sé, hay que probar en todas las configuraciones posibles), si se inspecciona el contenido de ese item:
NSLog( @"types %@", [ item types ] );
Se obtiene lo siguiente:
types (
"dyn.ah62d4rv4gu8yc6durvwwa3xmrvw1gkdusm1044pxqyuha2pxsvw0e55bsmwca7d3sbwu",
"dyn.ah62d4rv4gu8ye55trr00c6xpkvy0g7dmr71gc6x3mvy1g7cuqm10c6xenv61a3k",
"dyn.ah62d4rv4gu8ye55trr00c6xpnr4gc7dmsr4gw25xnbbg82pwqvnhw6df",
"dyn.ah62d4rv4gu8zs3pcnzme2641rf4guzdmsv0gn64uqm10c6xenv61a3k",
"public.url",
"dyn.ah62d4rv4gu8yc6durvwwaznwmuuha2pxsvw0e55bsmwca7d3sbwu",
"public.utf8-plain-text",
"public.url-name",
"com.apple.pasteboard.promised-file-content-type",
"com.apple.pasteboard.promised-file-url",
"dyn.ah62d4rv4gu8y6y4usm1044pxqzb085xyqz1hk64uqm10c6xenv61a3k"
)
Premio para los ingenieros de Apple. Lo que se arrastra desde Safari empaqueta un par de propiedades bastante interesantes: la url y el título de la página.
De ahí, es fácil extraer esos valores:
title = [[NSString alloc] initWithData: [ item dataForType: @"public.url-name" ] encoding:NSUTF8StringEncoding];
url = [[NSString alloc] initWithData: [ item dataForType: @"public.url" ] encoding:NSUTF8StringEncoding];
Dicho de otra forma: lo que se pasa desde Safari está bien empaquetado, de forma lógica, autodescriptiva, ordenada. Lo que nos gusta a los aprietateclas.
Pero, una vez lanzada la aplicación llega el primer email diciendo “oye, ¿esto funciona en Firefox?” Y claro, aquí viene lo bueno.
Porque ¿qué es lo que expone Firefox al arrastrar un link? Pues nada de nada:
types (
"public.utf8-plain-text",
"dyn.ah62d4rv4gu8y4554rf0g22n1rf0gk25bsmwa"
)
Simplemente, lo mismo que si se estuviera arrastrando un texto normal y corriente. Estupendo, el código que comprobaba que lo que se estuviera arrastrando fuera una url estaba basado en la existencia de las propiedades public.url y public.url-name, y rechazaba lo que sólo fuera public.utf8-plain-text. O, dicho de otra forma, bofetón en el lado que más duele.
¿La moraleja? La que ya deberíamos sabernos todos de siempre: que hay que probar en todas las configuraciones, y que cosas como los test units tienen una validez limitada, porque siempre hay que tener en cuenta que trabajamos sobre APIs desarrolladas por otros que pueden ser tan paquetes como nosotros.