Utiliser Git avec un projet XCode

28112008 Dans: Logiciel

Un des outils indispensable pour un développeur, est un gestionnaire de versions. Malheureusement XCode gère uniquement CVS, Perforce et Subversion. Si vous avez décidez d'aller voir du coté du gestionnaire distribué Git, voici un article de Christopher Roach sur son utilisation pour gérer un projet XCode :

Il est aussi possible de se servir uniquement de la liste des fichiers à ignorer pour l'adapter à Mercurial par exemple.

Livre: Programmation Cocoa sous Mac OS X

26112008 Dans: Cocoa, Livres

CouvertureOn l'attendait avec impatience, la voici. La version française de la troisième édition de Cocoa Programming for Mac OS X vient de paraître.

L'éditeur a changé (ce n'est plus Eyrolles), et nous ne pouvons pas encore vous donner notre avis sur la traduction, mais la version anglaise reste le seul livre indispensable à tout programmeur Cocoa. À commander au père Noël d'urgence.

Note de Fabien: Je peux vous dire qu'il est vraiment sympa pour l'avoir lu dans le cadre de la relecture technique de la version française.

iPhone DevCamp Paris 3

20112008 Dans: Conférences, iPhone / iPod Touch

Si vous êtes intéressé par le développement sur iPhone et que vous êtes sur Paris ce samedi 22 novembre, vous pouvez aller à la troisième édition de l'iPhone DevCamp Paris à La Cantine :

Faite vite pour vous inscrire, il ne reste que 4 places au moment où j'écris ce billet.

Vos débuts en Cocoa

19112008 Dans: Cocoa, Objective-C

Comme promis, cet article sera plus concret que les précédents, je ne vais toutefois pas vous épargner la théorie puisque nous allons aborder un concept important pour Cocoa, le paradigme M-V-C, et voir quelques rudiments du langage Objective-C et de l'utilisation de nos deux outils, XCode et Interface Builder.

Le programme d'exemple

Afin d'être plus concrètes, les explications s'articuleront autour d'un programme simple, pas très éloigné de l'exemple classique d'Apple, à savoir, le convertisseur de monnaie. Cependant, je m'adresse ici à des programmeurs chevronnés qui voudront rapidement en venir aux faits.

Le principe de notre programme est le suivant: une fenêtre comprend deux champs éditables. Taper une température dans le champ Degrés Fahreinheit et valider fait apparaître la conversion dans le champ Degrés Celcius et vice-versa.

Le paradigme M-V-C

À l'instar d'autres bibliothèques de développement, Cocoa est basée sur le paradigme Modèle-Vue-Contrôleur, qui sépare les Vues (l'interface utilisateur) du Modèle (la partie qui conserve les données et effectue les calculs). Le Contrôleur fait les liens entre les deux couches.

MVC

Création du projet

XCode impose la création d'un projet pour regrouper les différents fichiers constituant l'application et définir ses paramètres de construction.

Sous XCode, sélectionnez le menu File > New Project… > Application > Cocoa Application. Cliquez sur Next, tapez un nom pour le projet, et choisissez sa localisation. La fenêtre du nouveau projet s'ouvre; il y a déjà quelques fichiers dans le projet.

Programme principal

Jetez un œil à main.m, dans la rubrique Other Sources:

    #import <Cocoa/Cocoa.h>

    int main(int argc, char *argv[])
    {
        return NSApplicationMain(argc,  (const char **) argv);
    }

Nous reconnaissons la forme canonique utilisée en C pour la fonction main(). Elle ne fait qu'appeler NSApplicationMain() qui va essentiellement créer une instance de la classe NSApplication.

La directive de compilation #import est similaire à #include, si ce n'est qu'un fichier déjà inclus ne le sera pas une seconde fois. On inclut ici cocoa.h qui se trouve dans le framework Cocoa.

Ressources

Dans la rubrique Resources , vous trouverez trois fichiers:

  • Info.plist Comme vous le voyez, il s'agit d'un fichier XML. Vous pouvez d'ailleurs éditer les fichiers .plist grâce à l'utilitaire Property List Editor, mais ce fichier-là peut être édité d'une façon plus conviviale (…c'est vite dit) dans XCode (menu Project > Edit Active Target).

  • InfoPlist.strings Les fichiers .strings servent à traduire une application dans une autre langue — ce qu'on dénomme souvent par le vilain anglicisme localiser. Les clefs y sont associées aux texte traduits. Ce fichier-ci est utilisé pour le texte s'affichant dans la boîte de dialogue À propos de…

  • MainMenu.nib Ce fichier contient des éléments d'interface utilisateur. Double-cliquez-le pour l'ouvrir dans Interface Builder… il y a déjà du monde à l'intérieur.

Couche Vue

Faîtes en sorte que la fenêtre Window ressemble à ceci:

Fenetre

Vous trouverez les éléments dans la palette Library (menu Tools > Library), dans la rubrique Cocoa > Views & Cells. Les champs éditables sont des Text Fields. Les intitulés sont des Label.

Couche Modèle

Nous allons ici créer la classe CFRConvertisseur. Pourquoi pas Convertisseur tout court ? Traditionnellement, les noms de classes commencent par un suffixe pour éviter des conflits (il n'existe qu'un namespace par application). Les classes de Cocoa commencent par NS pour… Next Step.

Sous XCode, dans la fenêtre du projet, sélectionnez la rubrique Classes. Sélectionnez le menu File > New File… > Cocoa > Objective-C Class. Cliquez sur Next, vous serez alors invités à saisir le nom. Tapez donc CFRConvertisseur.m. Puis cliquez sur Finish. Deux fichiers, CFRConvertisseur.m et CFRConvertisseur.h, sont alors insérés dans le projet. Ouvrez donc le .h :

    #import <Cocoa/Cocoa.h>

    @interface CFRConvertisseur : NSObject {

    }

    @end

C'est ainsi que l'on déclare une classe en Objective-C. NSObject est l'objet de base, dont héritent tous les objets, à de rares exceptions près.

On place entre les accolades les définitions des variables d'instances (variables membres). Notre programme n'en nécessitant pas, nous les laissons vides. Nous définissons, entre l'accolade } et @end, les méthodes. Comme nos méthodes n'accèdent pas aux variables d'instance, nous les déclarons comme des méthodes de classes (ce qu'on appellerait des méthodes "statiques" en Java), en les précédant du signe + .

    + (float) convertirCelciusEnFahrenheit:(float)celcius;
    + (float) convertirFahrenheitEnCelcius:(float)fahrenheit;

Pour info: les méthodes d'instances sont précédées du signe - .

Copiez ces deux lignes et ouvrez CFRConvertisseur.m.

Pour ouvrir le .m correspondant au .h courant, et vice-versa, cliquez sur la petite icône counterpart (en haut à droite) ou bien utilisez le menu View > Switch to Header / Source File.

Collez les prototypes des méthodes, afin d'implémenter les formules de conversion:

    #import "CFRConvertisseur.h"

    @implementation CFRConvertisseur

    + (float) convertirCelciusEnFahrenheit:(float)celcius
    {
        return (9.0/5.0) * celcius + 32.0;
    }

    + (float) convertirFahrenheitEnCelcius:(float)fahrenheit
    {
        return (5.0/9.0) * (fahrenheit - 32.0);
    }

    @end

Couche contrôleur

Et maintenant, nous programmons la couche contrôleur, qui fait le lien entre les vues et le modèle. Créez un nouveau fichier source, appelé CFRControleur.m.

Déclarations des outlets

Ouvrez CFRControleur.h. Tout d'abord, nous déclarons les outlets:

    @interface CFRControleur : NSObject {
        IBOutlet NSTextField*   champFahrenheit;
        IBOutlet NSTextField*   champCelcius;
    }

Les outlets sont des variables d'instance, quand notre classe CFRControlleur sera instanciée (à la lecture du fichier .nib), Cocoa fera pointer les variables sur les objets que nous leur auront lié. Nous allons voir ces liaisons dans un instant. Ecrire IBOutlet est nécessaire pour qu'Interface Builder sache qu'il s'agit d'outlets.

N'oubliez pas de rajouter #import "CFRConvertisseur.h"

Déclaration des actions

    @interface CFRControleur : NSObject {
        IBOutlet NSTextField*   champFahrenheit;
        IBOutlet NSTextField*   champCelcius;
    }

    - (IBAction) fahrenheitModifie:(id)sender;
    - (IBAction) celciusModifie:(id)sender;

    @end

Les actions sont des méthodes qui sont appelées lorsqu'un contrôle est actionné. Pour nos champs, cela signifie qu'on aura validé leur contenu en tapant sur Entrée. Une action a forcément un prototype de cette forme. id est le type générique des objets. Nous savons évidemment qu'il s'agit de NSTextFields.

Regardez donc à quoi correspond le symbole IBAction

Sous XCode, pour accéder à la définition d'un symbole, maintenez la touche Commande appuyée, et double-cliquez le symbole.

On peut voir qu'IBAction est équivalent à void et qu'IBOutlet équivaut à rien.

Liaison des Outlets et Actions

Retournez sous Interface Builder. Faîtes apparaître la palette Library (menu Tools > Library). Dans la rubrique Library > Cocoa > Objects & Controllers, vous trouverez un cube bleu, intitulé NSObject. Glissez-le dans la fenêtre MainMenu.nib. Ainsi, Cocoa instanciera un objet de la classe NSObject à l'ouverture du .nib… mais ce n'est pas ce que nous voulons ! Sélectionnez le cube, puis dans la palette Inspector > Object Identity mettez le champ Class à CFRControleur. Vous remarquerez que les actions et outlets sont apparues au bas.

Cliquez sur le cube bleu en maintenant la touche Contrôle appuyée (ou bien clic droit), et reliez le cube au champ Fahrenheit. Quand vous lâchez le bouton, un menu apparaît: choisissez champFahrenheit. Et voilà! L'outlet, champFahrenheit est liée au champ la représentant. Faîtes de même pour le champ Celcius.

Pour les actions, c'est pareil, mais en tirant un segment du champ vers le cube. Je vous laisse faire.

Implémentation des actions

Revenons à XCode et à CFRControleur.m, pour y ajouter les deux méthodes d'actions:

    - (IBAction) fahrenheitModifie:(id)sender
    {
        // Afficher la température convertie dans le champ Celcius
        float fahrenheit = [sender floatValue];
        float celcius = [CFRConvertisseur convertirFahrenheitEnCelcius:fahrenheit];
        [champCelcius setFloatValue:celcius];
    }

Remarquez le [sender floatValue]. Il s'agit d'un appel de méthode, qu'on appelle plus volontiers un message en ObjC. Nous savons que sender est notre NSTextFieldFahrenheit. Nous lui demandons de nous envoyer sa valeur sous la forme d'un float.

[CFRConvertisseur convertirFahrenheitEnCelcius:fahrenheit] est également un message, mais comme convertirFahrenheitEnCelcius: est une méthode de classe, nous la faisons précéder du nom de sa classe.

Finalement, nous demandons au champ Celcius d'afficher la valeur celcius.

Ajoutons l'autre méthode:

    - (IBAction) celciusModifie:(id)sender
    {
        // Afficher la température convertie dans le champ Fahrenheit
        [champFahrenheit setFloatValue:[CFRConvertisseur convertirCelciusEnFahrenheit:[sender floatValue]]];
    }

Cette méthode est similaire à la précedente, si ce n'est que j'ai imbriqué les messages.

Terminez par ajouter

    #import "CFRConvertisseur.h"

Alors ça marche ?

Nous n'avons plus qu'à lancer le programme: menu Run > Run. Ça doit compiler et lancer l'application. Je vous laisse jouer et essayer quelques valeurs.

Quelques améliorations

Vous aurez peut-être remarqué que le programme souffre de deux défauts:

  • trop de chiffres sont affichés (c'est inesthétique)

  • si on entre des caractères plutôt que des chiffres, cela revient à taper zéro (c'est mal).

Retournez sous Interface Builder. Dans la palette Library > Library > Cocoa > Views & Cell, recherchez le Number Formater (un rectangle avec un $ ). Glissez-le sur le champ Fahrenheit. Allez dans la première rubrique de l'Inspecteur (Number Formater Attributes), et mettez-y le menu Style à Decimal. Faîtes de même pour le champ Celcius.

Retournez sous XCode, relancez l'application… les deux défauts sont réglés !

Pour finir

Cet article n'était qu'une introduction, mais vous a cependant présenté les concepts de bases de Cocoa: MVC, édition des .nib, Outlets et actions. Les prochains articles vous aideront à approfondir ces connaissances.

Le projet complet à télécharger, si vous n'avez pas réussi.

Des ressources sur Cappuccino

17112008 Dans: Cocoa.fr, Liens

J'avais parlé il y a quelques temps de Cappuccino, un framework permettant de concevoir des applications web similaires à ce que l'on trouve sur Mac. Il utilise pour ce faire le langage Objective-J que l'on peut voir comme un mix entre Objective-C et Javascript.

J'ai essayé de l'utiliser il y a quelques semaines, mais la documentation était assez sommaire. Quelques ressources récentes me donne bien envie de le tester à nouveau d'ici peu :

PS: Concernant plus particulièrement Cocoa.fr, j'ai modifié le fil RSS des commentaires pour inclure le commentaire dans son ensemble.

Le garbage-collector de Leopard

13112008 Dans: C, Cocoa, Objective-C

Pour ceux que cela interresserait, Le code du garbage collector de Leopard est disponible sous licence Apache 2.0 depuis peu. Le projet s'appelle AutoZone et il est aussi bien utilisé dans Cocoa que dans MacRuby. Il est disponible sur le site Open Source d'Apple :

Sortie de LLVM 2.4

12112008 Dans: C, Objective-C

La version 2.4 de LLVM, le projet permettant de créer des compilateur auquel Apple attache beaucoup d'importance (voir LLVM : Le futur compilateur d'Apple ? et 2008 LLVM Developers' Meeting), vient de sortir. Parmi les nouveautés il y a :

  • La gestion des Blocks
  • Beaucoup d'évolutions sur Clang qui devrait permettre à terme de proposer une remplacement à GCC. Il permet déjà à l'heure actuelle de compiler des projets comme SQLite, Lua ou ClamAV ainsi qu'une grande partie des exemples de code Obejctive-C de la documentation Apple.
  • Diverses optimisations concernant la vitesse de compilation.

Pour plus d'informations, vous pouvez lire :

Je parle bien de design

La plupart des gens confondent stylisme et design. Autrefois en français, on distinguait le dessin du dessein; l'homophonie a fait préférer le terme design à dessein, mais l'idée reste: le design, c'est la conception fonctionnelle, comment "marche" l'objet. Le stylisme, lui, n'est lié qu'à l'apparence d'un objet (et non pas son esthétique, il n'y a pas de notion de beau ici, juste celle de différenciation).

Les Mac sont des machines fortement designées. Il m'a toujours été difficile d'expliquer pourquoi j'avais fait le choix du Mac à des personnes qui ne connaissent que le PC. Elles ne comprennent pas pourquoi elles devraient payer plus cher pour un ordinateur, "seulement parce qu'il est plus beau". Certainement, si vous me lisez, vous utilisez un Mac, et vous savez pourquoi: vous avez acheté plus que du matériel, vous avez acheté une expérience. Vous aimez le Mac parce qu'il a été "pensé".

En tant que programmeur sur Mac, je suis aussi un utilisateur, et je m'arrange pour reproduire ce qui me plaît et bannir ce qui m'agace au quotidien. L'essentiel du travail de design se faisant sur l'interface utilisateur, les Apple Human Interface Guidelines restent un livre de chevet. Mais ce sont tout autant les années d'utilisation du Mac qui m'ont formé à sa culture: minimalisme, prévisibilité, cohérence.

J'ai eu l'occasion de parler avec un programmeur qui a un poste important chez un grand éditeur de logiciels d'apprentissage des langues. Nous parlions d'Eclipse, et je lui exprimais mon dégoût pour son interface. Il me répondit: " l'interface utilisateur, c'est avant tout une question de goût". Je ne peux pas être plus profondément en désaccord ! Il y a certes des habitudes, personnelles ou liées à l'utilisation d'une plateforme particulière, certes tout le monde ne pense pas pareil, ni n'a les mêmes aptitudes mentales, mais je suis convaincu que les trois piliers que j'ai cité plus haut (je les cite à nouveau: minimalisme, prévisibilité, cohérence) sont des principes qui peuvent s'appliquer à tous les cerveaux.

Votre rôle de designer: prendre des décisions

Voici un exemple. Un développeur a proposé que nous faisions des remarques sur son nouveau logiciel. Beaucoup de mes remarques portaient sur les Préférences, mais particulièrement sur une case à cocher. Cette case servait à activer la génération de l'aperçu QuickLook. Si, si, vous savez, QuickLook, le truc introduit par Apple avec Mac OS 10.5 et qui permet d'afficher l'aperçu des documents.

"C'est utile alors. Pourquoi tu ne le laisses pas activé tout le temps ?" lui demandais-je.

Parce que la génération de l'aperçu prend du temps. Mais si la génération n'est pas faite, le Finder met plus de temps à afficher l'aperçu", me répondit-il. Et un peu agacé par mes propos, il a laissé sa case à cocher.

Voyez-vous le travers ici ? Ce développeur n'a pas voulu faire de choix. Il laisse l'utilisateur le faire à sa place. Mettons-nous dans la peau de l'utilisateur: je me retrouve avec une case "Générer l'aperçu QuickLook", je la coche ou pas ? À mon avis, 9 personnes sur 10 préférerons ne pas y toucher. Dans celles qui restent, certaines iront voir la doc et ne seront pas plus avancées. Elles laisseront la valeur par défaut. Il reste peut être alors une infime portion d'utilisateurs qui vont tester ce qui leur convient le mieux. Le pire, c'est que le développeur devra quand même décider si la case doit être cochée par défaut ! Les conséquences sont les suivantes:

  1. vous avez troublé vos utilisateurs
  2. vous avez peut-être codé une fonction inutile
  3. vous avez dû documenter le rôle de cette case
  4. vous avez compliqué votre source (ce qui gâte son évolution et peut éventuellement produire des bogues)

Quelle était la bonne décision alors, puisque je sais tout ? Je dirais: Imposer la meilleure option à l'utilisateur. Si la génération de l'aperçu prend moins d'une seconde, alors c'est négligeable pour l'utilisateur. Mais mon vrai choix, en vrai, aurait été de ne tout simplement pas coder cette fonctionnalité. Je n'utilise jamais l'affichage Coverflow, et très rarement QuickLook. Et j'imagine qu'il en est de même pour tout le monde, sauf Steve Jobs, pour épater la galerie lors de ses conférences. D'ailleurs, je parie que Coverflow aura disparu dans Mac OS 10.8. Et même si j'ai tort, il y avait plein d'autres choses plus importantes à coder avant.

Pour finir, ne jetons pas la pierre à ce développeur — qui a pensé avant tout à ses utilisateurs — mais balayons déjà devant notre porte: Toi, lecteur, quels choix t'es-tu refusé à faire ?

Si vous développez en Python avec MySQL comme base de données et que vous êtes sous Mac OS X, les deux liens suivant peuvent vous être très utile :

En vrac

04112008 Dans: Cocoa, En vrac, Liens

Voici les dernières informations intéressantes sur le monde Cocoa :


Sponsors