Si vous proposiez déjà une application pour Mac et que vous souhaitez qu’elle soit disponible sur le Mac App Store, quelques modifications s’avèrent nécessaires. Le présent article prodigue quelques astuces pour créer la version pour le magasin d’Apple, tout en conservant la version distribuée sur votre site web.
S’assurer que l’application peut être commercialisée sur le MAS
Avant toute chose, il faut vous assurer que votre application pourra respecter les restrictions d’Apple. Il s’agit essentiellement que son installation puisse se faire par une simple copie.
BWToolkit
Apple interdit d’appeler des méthodes privées de ses API. Il se trouve justement qu’une framework très populaire, BWToolkit, fait appel à quelques API privées de NSTokenAttachmentCell. L’auteur est au courant; en attendant, il est possible de recompiler la framework en supprimant le code en défaut.
Enregistrement des données
Comme je l’expliquai, le but d’Apple est que la désinstallation de l’application soit aussi simple que sous iOS. Elle impose pour cela des restrictions quant aux répertoires destinés à accueillir les données de l’utilisateur. Pour ma part, j’ai dû changer le chemin d’enregistrement de la galerie des portraits de utilisateur/ Documents à utilisateur/ Bibliothèque/ Application Support/ PortraiMatic.
Nouvelle configuration ou nouvelle cible ?
Passons aux choses sérieuses. Apple impose que l’application pour le MAS ne contienne pas:
- de code PowerPC. Le MAS n’étant disponible qu’à partir de Mac OS 10.6.6, qui ne tourne que sur processeurs Intel.
- des frameworks pour mettre à jour l’application. Ici, on parle évidemment de Sparkle, dont l’absence est vérifiée par les validateurs d’Apple.
- des messages/boites de dialogues qui invitent à entrer un code de débridage. Ma première idée fut de créer une nouvelle “build configuration” pour le MAS. Seulement, cette tactique fonctionne mal: il est difficile de retirer des éléments. Par exemple, pour retirer Sparkle, il faudrait ajouter un script qui supprime la framework de l’application. Tout est à l’avenant: par exemple, il faut retirer des Préférences les rubriques liées aux Mises à jour et au débridage du logiciel. Finalement, il est plus simple de créer une cible (target) spécifique au MAS, pour incorporer ou retirer des fichiers à volonté.
Création d’une nouvelle cible
Dupliquez la cible actuelle par un clic droit > Duplicate Target. Renommez-la, en quelque chose comme MonAppMAS.
Modifier les configurations de la cible MAS
Affichez les build configurations de la cible. Nous modifions toutes les configurations (Debug, Release…).
Architectures i386 x86_64
Nous compilons pour les architectures Intel 32 et 64 bits.
Base SDK Mac OS 10.6
Le MAS n’étant disponible qu’à partir de 10.6.6, adoptons la dernière version du SDK.
Valid Architectures i386 x86_64
Liste des architectures éventuellement à compiler. Seules celles qui se trouvent à la fois dans cette liste et dans ‘Architectures’ seront compilées.
Build Locations Build Product Path build/MAS
Nous créons un sous-dossier dans le répertoire Build pour la version réservée au MAS. Modifiez également ce paramètre pour la cible originelle, par exemple en build/MonSite. En effet, certaines ressources sont références par des chemins relatifs au répertoire Build; il faut alors que le Build Product soit enfoui dans un même nombre de sous-répertoires.
GCC 4.2 – Preprocessing Preprocessor Macros Not Used in Precompiled Header MAC_APP_STORE
Je définis un symbole MAC_APP_STORE qui sera utilisé dans le code pour faire de la compilation conditionnelle:
#ifdef MAC_APP_STORE
NSLog(@"Version pour le Mac App Store");
#else
NSLog(@"Version pour mon site web");
#endif
Packaging Info.plist File Info.plist
En dupliquant la cible, Xcode a aussi créé un deuxième fichier Info.plist. Nous n’en voulons qu’un seul pour les deux cibles, aussi nous supprimons ce deuxième fichier et déclarons le même fichier.
Preprocess Info.plist File YES
Ceci active une étape de pré-traitement sur le fichier Info.plist. Nous l’activons pour permettre sa compilation conditionnelle.
Info.plist Other Preprocessor Flags -traditional
Une fois le pré-traitement activé, le compilateur considère que les // indiquent le début de commentaires. Cela pose problème avec les URL (http://monsite.com). Passer le drapeau -traditional au compilateur l’oblige à considérer que les commentaires ne peuvent être délimités que par /* et */ comme dans le langage C traditionnel. Plus d’infos par ici.
Info.plist Preprocess Definitions MAC_APP_STORE
Nous définissons le symbole MAC_APP_STORE pour la compilation d’Info.plist.
Search Paths Framework Search Paths
Il faut reprendre ces chemins pour supprimer les frameworks inutiles (ex. Sparkle.framework) mais également pour supprimer les / que Xcode ajoute malencontreusement aux chemins, lors de la duplication de la cible. Il s’agit d’un bogue de Xcode 3.2.5.
Editer Info.plist
Les réglages plus haut permettent l’utilisation de la compilation conditionnelle. Clic doit sur Info.plist > Open As > Source Code File…
#ifdef MAC_APP_STORE
<LSMinimumSystemVersion> <10.6.6>
<LSApplicationCategoryType><public.app-category.photography>
#else
<LSMinimumSystemVersion><10.5.0>
<SUEnableAutomaticChecks>
<SUPublicDSAKeyFile><dsa_pub.pem>
<SUFeedURL><http://ceroce.com/portraimatic/appcast.xml>
#endif
N’avoir qu’un seul Info.plist est intéressant parce que seule une poignée de clef sont différentes pour la MAS.
Retirer les sources et ressources inutiles
Demandez les infos sur le fichier source ou ressource pour le retirer de la cible à laquelle il n’appartient pas et donc réduire la taille de l’application. À noter qu’il peut être nécessaire de créer deux fichiers ressources. Par exemple, j’ai dû créer un fichier PreferencesMAS.xib, pour que ne soient pas affichées les rubriques liées aux Mises à jour de l’application.
Pour la suite
À ce stade, vous devriez avoir deux applications bien différenciées. Il reste encore deux étapes avant la soumission à Apple:
- signer l’application
- implémenter la vérification du reçu d’Apple
Ce sont deux étapes complexes qui feront l’objet d’un autre article.
20 mai 2011: Mise à jour
Voici quelques précisions supplémentaires sur Info.plist et sa compilation conditionnelle:
- J’ai fait une fausse manipulation pour la version PortraiMatic actuellement proposée sur le MAS: j’avais bien modifié le fichier Info.plist comme indiqué ci-dessus; cependant j’ai eu le malheur d’afficher son contenu dans Xcode en mode ”graphique” et d’enregistrer, si bien qu’Xcode a fait disparaître sa compilation conditionnelle. De fait, les clefs de Sparkle apparaissent dans l’Info.plist et la version minimum du système d’exploitation est fixée à 10.5. Apple a validé cette application sans broncher.
- Louka Desroziers a eu quelques soucis, en voulant imbriquer des #ifdef. Il faut absolument qu’ils soient placés en début de ligne (sans espace avant).