web-dev-qa-db-fra.com

Comment configurer des ensembles indépendants de paramètres d'exécution dans XCode

Mon application iPhone se connecte à trois serveurs différents, à savoir: production , staging et test . Il existe de nombreuses valeurs de configuration que l'application utilise en fonction du serveur auquel elle se connecte, par exemple. Identifiant de l'application Facebook, clé de l'équipe TestFlight, etc.

Je voudrais avoir tous les paramètres dans GIT et ne sélectionnez que la configuration que l'application est supposée utiliser lors de la compilation ou de la publication. Par exemple, lorsque testing est sélectionné, Product -> Run dans XCode exécute la version de débogage de l'application qui se connecte à testing et Product -> Archive crée le fichier IPA. avec la version de publication qui se connecte également à testing .

Je ne veux pas créer plus de configurations de construction que de débogage et de publication (car cela impliquerait 6 combinaisons différentes de configurations de construction/configurations d'exécution). La solution idéale, selon moi, consisterait en trois schémas: production , testing et staging , et chaque schéma sélectionne l'un des trois fichiers Info.plist à utiliser avec le application. Cela me permettrait non seulement de définir différents paramètres d'exécution, mais également différentes versions d'applications ou identifiants de bundles en fonction du serveur principal. Mais il ne semble pas que je puisse configurer l'action Archiver autrement qu'en sélectionnant une configuration de construction différente. Des idées si cela pourrait être réalisé de quelque façon?

Éditer: Pour que ce soit un peu plus clair, production/staging/testing est le serveur principal, pas la version de l'application iOS. L'application iOS est disponible en deux versions: debug/release . En d’autres termes, je souhaiterai peut-être exécuter une version debug de l’application qui se connecte au production server, par exemple, pour déboguer une panne provoquée par le code JSON renvoyé par ce serveur. J'aurais pu nommer les serveurs A, B et C pour des raisons de clarté.

57
Amiramix

Je suggérerais d'utiliser différentes cibles de construction pour chaque environnement. J'ai déjà utilisé ce modèle avec succès. Dans les paramètres de votre projet, vous pouvez dupliquer la cible actuelle et modifier les paramètres de construction selon vos besoins. Il existe une propriété Info.plist File qui vous permettra de modifier le plist par défaut pour cette cible. 

Après cela, vous pouvez créer un schéma pour chaque environnement qui utilisera la cible correspondante. 

Vous pouvez aller plus loin et utiliser un identifiant de bundle différent pour chaque cible et différents noms. Cela vous permettra par exemple d’installer les versions intermédiaire et de production sur le même périphérique. 

Le seul inconvénient est que vous avez plus de travail lorsque vous souhaitez mettre à jour les profils de provisioning. 

10
adig

Un bon moyen de le faire serait d'utiliser des configurations de construction et des macros C. Cela évite d'avoir à créer une cible distincte pour chaque configuration, ce qui n'est pas vraiment l'utilisation correcte des cibles.

Tout d'abord, vous voulez configurer les configurations au niveau du projet:

enter image description here

Vous pouvez créer différentes configurations pour le débogage, la distribution d'entreprise et tout autre type de construction spéciale de votre choix.

Ensuite, vous pouvez définir des drapeaux de macro pour chaque configuration qui seront transmis au compilateur. Vous pouvez ensuite rechercher ces indicateurs lors de la compilation. Recherchez le paramètre de génération "Indicateurs de préprocesseur" au niveau cible:

enter image description here

Si vous développez le triangle, vous pouvez définir différentes valeurs pour chacune de vos configurations. Vous pouvez définir des macros KEY=VALUE ou seulement KEY ici.

enter image description here

Dans votre code, vous pouvez vérifier l'existence de ces macros ou leur valeur (s'il en existe une). Par exemple:

#ifdef DISABLE_FEATURE_X
    featureXButton.hidden = YES;
#endif

// ...

#if FOOBAR_VISIBLE == 0
    foobarView.hidden = YES;
#Elif FOOBAR_VISIBLE == 1
    foorbarView.hidden = NO;
#else
    #error Invalid value for FOOBAR_VISIBLE
#endif

Vous pouvez également transmettre des valeurs de chaîne, qui doivent être entourées de guillemets simples dans le paramètre de construction, par exemple. DEFAULT_LOCALIZATION_NAME='@"en"'.

Vous pouvez également configurer la configuration utilisée pendant le temps de débogage et d'archivage à l'aide de l'éditeur de schémas. Si vous choisissez "Exécuter" ou "Archiver" dans l'éditeur de schémas, vous pouvez sélectionner la configuration appropriée.

enter image description here

Si vous devez paramétrer des entrées dans le fichier Info.plist, vous pouvez définir leur valeur à l'aide d'un paramètre de génération personnalisé. Ajoutez un paramètre de construction personnalisé pour votre cible:

enter image description here

Et puis donnez-lui une valeur appropriée pour vos différentes configurations:

enter image description here

Ensuite, dans le fichier Info.plist, vous pouvez référencer ce paramètre:

enter image description here

Notez que la seule limitation de cette approche est que vous ne pouvez pas modifier les éléments suivants:

  • Paramètres.bundle

En outre, dans les anciennes versions de Xcode sans prise en charge du catalogue d'actifs, vous ne pouvez pas modifier les éléments suivants:

  • Icon.png
  • Default.png

Celles-ci ne peuvent pas être explicitement définies dans le fichier Info.plist ou ailleurs, ce qui signifie que vous avez besoin de différentes cibles pour les modifier.

J'espère que cela t'aides.

112
Mike Weller

Voici une solution bien plus simple si les bibliothèques concernées permettent de définir les clés dans le code, ce qui signifie que vous pouvez avoir une valeur de production dans votre fichier plist, mais que vous les modifiez dans votre AppDelegate (ou le fichier dans lequel ils sont utilisés en premier).

Fonctionne avec Facebook, Twitter et Google SDK pour le moment.

Ex:

#ifdef DEBUG
  // Facebook
  [FBSettings setDefaultAppID:@"SandboxID"];
  // Fabric / TwitterKit - must be called above [Fabric with:@[TwitterKit]];
  [[Twitter sharedInstance] startWithConsumerKey:@"SandboxKey" consumerSecret:@"SandboxIDSecret"];
#endif

Idem dans Swift, utilisez simplement #if au lieu de #ifdef.

Note à propos de Facebook Cela fonctionnait avec la version 3 de leur SDK, je ne suis pas sûr que ce soit possible avec les versions ultérieures.

2
Nycen

C'est probablement une technologie très basse, mais je viens d'avoir une méthode appelée apiURL() qui renvoie l'URL de l'API que je veux. J'ai l'hôte local, la scène et la production et je ne fais que commenter celui que je veux. Cela a bien fonctionné pour moi jusqu'à présent. J'ai seulement oublié de le changer plusieurs fois. Oops.

0
Dan