我的iPhone应用程序连接到三个不同的服务器,例如:生产,暂存和测试。应用程序使用了一堆配置值,具体取决于它连接到哪个服务器,例如: Facebook App ID,TestFlight团队密钥等
我想在GIT中拥有所有设置,并且只选择应用程序在编译或发布时应该使用的配置。例如,选择测试时,产品 - >在XCode中运行运行连接到测试的应用的调试版本,以及产品 - >存档创建IPA文件,其版本也连接到测试。
我不想创建比调试和发布更多的构建配置(因为这意味着构建配置/运行时配置的6种不同组合)。我认为理想的解决方案是,我有三个方案:生产,测试和暂存,每个方案选择一个三个与应用程序一起使用的Info.plist文件。这将允许我不仅定义不同的运行时设置,还根据后端服务器定义不同的应用程序版本或包标识符。但是,除了选择不同的构建配置之外,我看起来不能以任何其他方式配置存档操作。任何想法,如果可以以任何方式实现?
编辑为了使其更清晰,生产/登台/测试是后端服务器,而不是iOS应用程序的版本。 iOS应用程序有两个版本:调试/发布。换句话说,我可能想要运行连接到生产服务器的应用程序的 debug 版本,例如调试由该服务器返回的JSON导致的崩溃。为了清楚起见,我本可以将服务器命名为A,B和C.
答案 0 :(得分:112)
执行此操作的好方法是使用构建配置和C宏。这样就不必为每个配置创建一个单独的目标,而这个目标实际上并没有正确使用目标。
首先,您要在项目级别设置配置:
您可以为调试,企业分发以及任何其他类型的特殊构建创建不同的配置。
接下来,您可以为将传递给编译器的每个配置定义一些宏标志。然后,您可以在编译时检查这些标志。在目标级别找到“预处理程序标志”构建设置:
如果展开三角形,则可以为每个配置定义不同的值。您可以在此处定义KEY=VALUE
或仅KEY
个宏。
在您的代码中,您可以检查这些宏的存在性或它们的值(如果有的话)。例如:
#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
您也可以传入字符串值,这些值必须在构建设置中用单引号括起来,例如DEFAULT_LOCALIZATION_NAME='@"en"'
。
您还可以使用Schemes编辑器配置在调试和存档时间内使用的配置。如果在Schemes编辑器中选择“Run”或“Archive”,则可以选择适当的配置。
如果需要参数化Info.plist文件中的条目,可以使用自定义构建设置定义其值。为目标添加自定义构建设置:
然后为您的不同配置提供适当的值:
然后在Info.plist文件中,您可以引用此设置:
请注意,此方法的一个限制是您无法更改以下项目:
此外,在没有资产目录支持的旧版Xcode中,您无法更改以下项目:
这些不能在Info.plist文件中或其他任何地方明确定义,这意味着您需要不同的目标来更改它们。
希望这有帮助。
答案 1 :(得分:10)
我建议为每个环境使用不同的构建目标。我以前成功使用过这个模型。在项目的设置中,您可以复制当前目标并根据需要更改构建设置。有Info.plist File
属性可让您更改该目标的默认plist。
之后,您可以为将使用相应目标的每个环境创建一个方案。
您可以更进一步,为每个目标和不同的名称使用不同的包ID。这将允许您在同一设备上安装分段和生产版本。
唯一的缺点是,当您想要更新配置文件时,您还有更多工作要做。
答案 2 :(得分:2)
如果相关的lib允许在代码中设置密钥,这意味着您可以在plist文件中拥有生产价值,但在AppDelegate中更改它们(或者在它们首次使用的文件中) )。
目前与facebook,twitter和google sdk合作。
例如:
#ifdef DEBUG
// Facebook
[FBSettings setDefaultAppID:@"SandboxID"];
// Fabric / TwitterKit - must be called above [Fabric with:@[TwitterKit]];
[[Twitter sharedInstance] startWithConsumerKey:@"SandboxKey" consumerSecret:@"SandboxIDSecret"];
#endif
同样在Swift中,只需使用#if而不是#ifdef。
关于Facebook的说明这适用于其SDK的第3版,我不确定它是否适用于更高版本。
答案 3 :(得分:0)
技术可能非常低但我只有一个名为apiURL()
的方法,它返回我想要的API的URL。我有本地主机,舞台和制作,我只是取消注释我想要的那个。到目前为止,它对我来说效果很好。我只是忘了把它换回几次。糟糕。