On l'a vu dans l'épisode 1 de "Passer de cron à launchd", la syntaxe de launchd est vraiment très verbeuse par rapport à celle des crontabs. De plus, launchd pose rapidement des problèmes quand il s'agit de définir des périodicités un peu excentriques ou sophistiquées.
Par exemple, si dans cron je veux créer une tâche qui s'exécutera toutes les 30 minutes tous les jours, j'écris ceci :

*/30 * * * *      /ma/commande
Alors, crond va lancer /ma/commande à 0h00, 0h30, 1h00, ... 23h30 tous les jours.
Pour faire la même chose avec launchd J'ai a priori deux possibilités : StartInterval et StartCalendarInterval. StartInterval est simple et permet de régler en 2 lignes mon intervalle de temps :
<key>StartInterval</key>
<integer>1800</integer>
Seulement, il existe une limitation de taille. StartInterval ne sait pas qu'il doit commencer à 0 minute pour assurer le rythme "heure + 0 minute, heure + 30 minutes". Si le plist launchd est chargé à 7h42, heure du démarrage de la machine par exemple, et bien la première exécution va se produire immédiatement. La prochaine aura bien lieu 30 minutes après, et ainsi de suite. On aura donc les heures de lancement suitantes : 7h42, 8h12, 8h42, ...

Si vous avez besoin d'un lancement à heure fixe, il faut donc oublier complètement StartInterval et vous rabattre sur StartCalendarInterval. Ce dernier impose les dates et heures de lancement, mais il souffre de deux gros défauts.
Premier défaut, et non des moindres : jusqu'à Mac OS X 10.5 le comportement de StartCalendarInterval était bugué, ce qui le rendait pratiquement inutilisable. D'ailleurs, je n'ai pas de certitude absolue sur son bon fonctionnement dans Leopard. Le second défaut, c'est la verbosité de sa syntaxe. Reprenons l'exemple ci-dessus, et transposons-le à StartCalendarInterval. On obtient le code suivant, juste pour la gestion de la périodicité :

<key>StartCalendarInterval</key>
<array>
	<dict>
	    <key>Minute</key>
	    <integer>0</integer>
	</dict>
	<dict>
        <key>Minute</key>
        <integer>30</integer>
	</dict>
</array>
Maintenant, imaginez le nombre de lignes nécessaires pour imposer un lancement aux minutes 0, 10, 20, 30, 40, et 50 : 27 lignes sans compter la gestion de la commande, de l'utilisateur, du header xml..., là où une seule ligne de crontab suffit.

Passons aux choses sérieuses avec un exemple de la vraie vie. Je veux lancer un script de sauvegarde sur ma machine professionnelle, à 12h30 et à 18h30, du lundi au vendredi. Avec cron, c'est simplissime :

30 12,18 * * 1,2,3,4,5      /mon/script/de/sauvegarde
Maintenant, si on veut reproduire la même chose avec launchd, on obtient un fichier xml très long. Je peux placer dans le même bloc dict au maximum une fois chaque mot clé (ici Minute, Hour, Weekday). Heureusement, les astérisques dans la crontab ne sont pas reportées dans launchd car un mot clé absent dans le plist correspond à une astérisque dans la crontab. Je n'ai qu'une valeur pour le mot clé Minute, j'ai deux valeurs pour le mot clé Hour, et 5 pour Weekday. Donc je vais avoir 2 blocs dict pour chaque jour (un pour chaque heure), et chaque bloc va faire 8 lignes. J'ai 5 jours, et 2 blocs de 8 lignes pour chacun, donc j'obtiens 80 lignes de xml uniquement pour la définition de la périodicité ! Ci-dessous, les 16 premières lignes :
<dict>
	<key>Weekday</key>
	<integer>1</integer>
	<key>Hour</key>
	<integer>12</integer>
	<key>Minute</key>
	<integer>30</integer>
</dict>
<dict>
	<key>Weekday</key>
	<integer>1</integer>
	<key>Hour</key>
	<integer>18</integer>
	<key>Minute</key>
	<integer>30</integer>
</dict>
Merci Apple pour cette simplification.