#BuggyXcode #BuggyApple

Marcos Sorribas
MarMass
Published in
5 min readNov 8, 2016

Se acabó. Llevo alrededor de tres años programando y usando casi a diario las herramientas de desarrollo y frameworks que Apple proporciona a “sus desarrolladores”. Esos mismos desarrolladores que crean sus apps, sin las cuales el iPhone o el iPad no valdrían NADA. Pues bien, en este tiempo el número de bugs/crashes por hora de trabajo -nueva métrica que me acabo de inventar- se ha disparado como una KPI de la siguiente startup en levantar una millonada de financiación. Y como arreglarlo está fuera de mi alcance, al menos voy a inventar una forma de reducir la ira e impotencia que me produce. ⚠️⚠️ Spoiler: Si eres un fanboy de Apple NO pierdas tu tiempo leyendo esto. ⚠️⚠️

El problema

¿Cuantas veces se os ha “cerrado inesperadamente” vuestro IDE de trabajo en los últimos dos días? ¿Soy el único al que la respuesta a esa pregunta es 4 o 5 -con suerte-? Y si, trabajo en Swift y con un Xcode GM pero ¿acaso la velocidad de releases no lo hace obligatorio?

Esto al principio no pasaba, Xcode antes era una mierda pero una mierda que nos gustaba -nuestra mierda💩-, ahora es que no hay quien lo utilice sin que le entren ganas de hacerse desarrollador de Windows Phone.

La excusa

Pero tranquilos, he leído por muchos sitios que todos los bugs que hay se deben a que estamos en una etapa de “transición”. Cuando esta “transición” finalice ya seremos todos felices. No volveremos a ver un [corchete] de Objetive-C en nuestra vida y podremos refactorizar código de Swift como si no hubiera un mañana -siempre y cuando ya lo hayamos migrado de Swift 1 a Swift 2 y a Swift 2.1 y a Swift 2.2 y ¿finalmente? a Swift 3….-

Si amigos, una transición a la mismísima mierda. Esa misma transición que quita puertos al nuevo MBP para adelgazarlo un poco y sin embargo ahora necesito dos adaptadores para enchufar mis dos pantallas externas por HDMI y thunderbolt, además de otro adaptador para conectar el iPhone y otro más el disco duro externo y ¡¡ostias!! al final se me ha apagado el pc porque tengo todos los puertos ocupados y no lo puse a cargar….

Así pues, basta de transiciones. Si las cosas NO funcionan, no hay que buscar excusas. Es porque están MAL hechas. Pero tranquilos que ya me ocupo yo de solucionar todos esos problemas de golpe.

La NO solución: #BuggyXcode

¿Nadie ha pensado que igual el Xcode tiene sentimientos? A lo mejor solo quiere que le presten atención y por eso “ termina inesperadamente” lo que estaba haciendo -igual que cuando un niño llora para que su madre le haga caso-

Yo me he parado a pensar en eso y al final he decidido darle voz y voto a mi Xcode. A partir de ahora los crashes de mi Xcode tendrán acceso directo a mi cuenta de Twitter de esta manera cuando mi Xcode pete podrá hacérselo saber a toda mi TL, todo Apple y al mismísimo Jobs si es que tiene Wifi en el más allá.

Primer paso: Observar

Lo primero de todo es saber que pasa cuando se produce un crash en una aplicación del sistema. Buscando un poco por internet, resulta que cada crash queda registrado en un archivo .crash dentro del directorio ~/Library/Logs/DiagnosticReports Lo único que tenemos que hacer es crear un observador de dicho directorio que ejecute un script cada vez que se añada un archivo dentro.

Para ello vamos a usar un framework del sistema llamado launchctl. Explicado brevemente, launchctl es un conjunto de herramientas que nos permite configurar observadores a directorios concretos de nuestro sistema para que se ejecuten cada vez que se modifican. Funciona mediante plist y con dos sencillos comandos de terminal.

//Añade el observador al sistema 
launchctl load MY/PATH/TO/watch.plist
//Elimina el observador del sistema
launchctl unload MY/PATH/TO/watch.plist

Ese plist que menciono es el siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.marmass.buggyxcode</string>
<key>Program</key>
<string>/RUTA/A/EL/SCRIPT/QUE/QUIERES/QUE/SE/EJECUTE/xcode_speak.sh</string>
<key>WatchPaths</key>
<array>
<string>/Users/Marcos-Mac/Library/Logs/DiagnosticReports</string>
</array>
</dict>
</plist>

El campo Label es un identificativo del proyecto que se trata. Por su parte el campo Program contiene la ruta al script (en bash) que queremos que se ejecute cuando el directorio que observamos sufre alguna modificación. Finalmente indicamos que queremos observar un directorio con la key WatchPaths e incluimos dentro el path al directorio que queremos observar que es donde se almacenan los archivos .crash generados por el sistema (~/Library/Logs/DiagnosticReports)

Segundo paso: Ejecutar

El script que queremos que se ejecute debería hacer lo siguiente:

  1. Recorre todos los archivos allí almacenados (ficheros .crash) filtrandolos por nombre. En mi caso buscaré nombres que contengan Xcode o SourceKitService porque le tengo especial manía a ese crash de Xcode.
  2. Se asegura que acaba de ocurrir filtrandolo por fecha. Afortunadamente el nombre de cada archivo contiene el timestamp de cuando se agregó. Basta con compararlo con Año-Mes-Dia-Hora-Minuto-Segundo actual y tenemos el que acaba de suceder.
  3. Se conecta con mi cuenta de Twitter y pone el siguiente Tweet: “Kabuuuuuuum 💥💥💥 #BuggyXcode says hello again!”

Siguiendo los requisitos, el script que yo uso es el siguiente:

#!/usr/bin/php
<?php
require "~/PAHT/TO/twitteroauth-master/autoload.php";
use Abraham\TwitterOAuth\TwitterOAuth;
$access_token = "TWITTER_APP_ACCESS_TOKEN";
$access_token_secret = "TWITTER_APP_SECRET_TOKEN";
$connection = new TwitterOAuth(TWITTER_APP_SECRET_KEY, TWITTER_APP_PUBLIC_KEY, $access_token, $access_token_secret);
$crash_count = 0;
$should_tweet = false;
$dir = opendir(getenv("HOME")."/Library/Logs/DiagnosticReports/");
while ($file = readdir($dir)) {
if (!is_dir($file)) {
if (strstr($file, "Xcode") or strstr($file, "SourceKitService")) {
$crash_count++;
date_default_timezone_set('Europe/Madrid');
$timestamp = date("Y-m-d-Hi");
if (strstr($file, $timestamp)) {
$should_tweet = true;
}
}
}
}
if ($should_tweet) {
$emjois = array("😩","🤔","🙃","😭","😤","😔");
$statues = $connection->post("statuses/update", ["status" => "Kabuuuuuuum 💥💥💥💥 #BuggyXcode says hello again!.... Crashes: ".$crash_count." ".$emjois[$crash_count % count($emjois)]]);
}
?>

Como habréis notado es muy sencillo. Se trata de un script de PHP que hace exactamente lo mencionado arriba. Para conectarte con la API de Twitter he optado por utilizar esta librería que es tan sencilla que con una línea has publicado el tweet. Aparte de eso tienes que haberte creado una app en tu cuenta de Twitter para obtener tus claves y tokens necesarios para poder publicar tweets, si buscas en google hay miles de tutoriales que lo explican.

Nota: Si intentais publicar de seguido un tweet muy parecido el API de Twitter no te deja y devuelve un 403 por si veis que no se publican todos vuestros crashes.

Tercer paso: It just works

Con el script cargado tan solo es necesario programar un rato hasta que se produzca el primer crash y ver como todo simplemente funciona….

buggyxcode

Las conclusiones

Creo que se ha notado que esto no vale para nada pero al menos yo estoy más tranquilo al saber que cada vez que Xcode me hace sufrir mi TL sufre conmigo.

No se si algun alma lectora está tan desesperada como yo y necesita esta medicina. Por si acaso he subido los scripts que estoy usando a mi github bajo la licencia hazloquequierasconellos así pues, hasta la próxima.

M.

--

--

Marcos Sorribas
MarMass
Editor for

Mitad estudiante de Ingeniería Informática y ADE en la UC3M. Mitad desarrollador iOS en minube. Eterno proyecto de millonario 💸💸