iOS 多环境配置

看到一篇对iOS多环境配置介绍不错的文章,翻译了一下,原文链接这里:

原文链接

下面的例子展示了如何在Xcode中对多环境进行配置。

动机


在我们开发应用的时候,你可能需要不同的环境。举个例子,比如在AdHoc和Appstore两种发布方式中会用不同的URL链接。XCode提供了简单的机制让这些成为可能:Configurations

最终目的:

不同的环境有不同的的configuration文件。如果我们有1个或多个文件对应每个环境,我们可以根据实际情况来改变URL,从测试服务器到生产服务器。

不同的环境有不同的bundle id,bundle name,app icon。这样的话我们可以直接确定设备上安装的是什么版本。也许更重要的是,允许在设备上同时安装不同环境的版本,因为每个环境有不同的bundle id。

不同环境有对应的预编译宏激活对应代码。这能够为你想在某个环境需要激活一段代码,但在另一个环境屏蔽的时候提供便利。举个例子,日志会在开发模式下启用,但是在AdHoc和App Store屏蔽。

为项目添加configuations


不知道你清楚不清楚,当你创建一个新的project的时候,Xcode已经提供了2个configurations:DebugRelease。

这些configurations的好处是,你能够在当前激活的configuration下更改build setting。而且,你可以通过 build scriptscustom build setting获取到当前激活的configuration。通过这个技术,我们可以改进我们的项目设置。我们的GitHub示例项目就是基于这个技术。文章剩下的部分,我们将指导你这是如何做到的。

我们已经创建了一个另外的configuration。命名为:AdHoc,这意味着我们将用于AdHoc发布。

添加一个configuration,你需要选中你的project(the root in the Project Navigator),然后定位到Configurations选项卡,在Editor菜单中,选择Add Configuration,然后选择Duplicate “release” Configuration。好了,到此你已经创建了一个新的configuration了。

你也可以通过+按钮来添加configuration

为了激活新建的configuration,我们需要告诉Xcode在build scheme中使用它。

在build scheme指定configuration


我们将创建一个新的scheme用于AdHoc发布。到Product菜单中,选择SchemeManage Schemes…

选择当前应用的building scheme,点击左下角的齿轮,并选择Duplicate。

默认情况下应用的building scheme和项目名称一致

在新打开的对话框内,修改scheme的名称,比如:应用名称Ad Hoc。然后选择Archive选项,然后给Adhoc设置Configuration。点击OK按钮确认

如果你是跟其他人一起合作这个项目,那么他们将看不到这个新的scheme,因为你还没有共享它。通过勾选单选框Shared,来共享原来的和新建的这个scheme。如果你提交了这些到你的版本控制系统中,那么其他人将会能够使用这些schemes。

为不同的环境设置不同的配置值


到现在,我们已经完项目,来应对每个环境不同的configurations,让我们好好利用起来。

我们首先在项目中创建一个文件夹结构,然后每个文件夹中放置一个configuration文件。下一步,我们添加一个额外的build phase,以保证在app运行的时候能够使用正确的文件。

来,我们首先在“Supporting Files”组下创建一个“config”组。

这是一个保证你的项目整洁的建议.也就是最终文件在硬盘中的位置。

创建Config组之后,创建三个跟configuration相同名字的文件夹。在我们这个具体情况是,DebugAdHocRelease。在每个文件夹下各创建一个Plist文件。

确认下,你保存的文件结构如下:

<source root folder>/config/<configuration>/Configuration.plist

souce root folder是处于跟.xcodeproje 文件同一目录的文件夹.它通常跟project文件同名,并且通常AppDelegate文件在其中。configuration文件夹必须和不同的configuration匹配,他们是大小写敏感的。

你可以手动创建必要的文件夹和文件,把他们添加到Xcode中


为了确保我们在每个环境中只使用对应的配置,让我们把刚才添加的文件从应用的Target中移除。有以下不同的方式做到:

Project Navigator中选择文件,然后在File InspectorTarget Memebership下取消单选框;

在Project主目录中选择target,然后选择Build Phase,从Copy Bundle Resources选线卡中移除文件;

在向Xcode中添加或创建文件的时候,在target栏中取消对应的单选框;

最后一步,在编译的时候把对应的配置文件拷贝到程序bundle中。需要做的是,到Project主目录,选择相应的target,然后选择Build Phases标签栏。接下来,我们要做的是添加一个Build Phase。从Xcode5开始,你需要从菜单里完成这些。所以,回过头,在Xcode菜单中选择Editor,然后选择Add Build Phase-Add Run Script Build Phase。新的Build Phase已经被添加,让我们给这个Build Phase改个名字,比如:Copy Configuration FIles。如果你是按照我们建议的方式创建的配置文件,你可以拷贝如下脚本:

RESOURCE_PATH=${SRCROOT}/${PRODUCT_NAME}/config/${CONFIGURATION}

BUILD_APP_DIR=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app

echo "Copying all files under ${RESOURCE_PATH} to ${BUILD_APP_DIR}"

cp -v "${RESOURCE_PATH}/"* "${BUILD_APP_DIR}/"

这段脚本将拷贝所有你指定的配置文件夹中的文件到bundle文件夹。有一点很重要,即保持拷贝到Bundle的资源和刚才添加的phase一致。

现在编译你的项目,并检查输出。你将会看到echo的信息和拷贝的文件列表。

使用配置项


使用configuration文件,需要使用NSBundle类。更具体的说,你只需要从应用bundle中获取配置文件路径。接下来展示了如果做:

- (NSString *) readValueFromConfigurationFile {

NSBundle *bundle = [NSBundle mainBundle];

NSString *path = [bundle pathForResource:@"Configuration" ofType:@"plist"];

NSDictionary *config = [NSDictionary dictionaryWithContentsOfFile:path];

return config[@"configParameter"];

}

//代码片段来自示例项目,DRYShowConfigurationViewController类。

记住,你也可以获取应用的info.plist文件,具体说可以方便的展示这些信息到关于页面或者其他页面。

NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];

NSString *bundleId = infoDictionary[@"CFBundleIdentifier"];

NSString *bundleVersion = infoDictionary[@"CFBundleVersion"];

为应用发布或编译不同的版本


虽然不同环境有了不同的配置已经很不错了,但是最有用的是在同一时刻,设备上可以安装不同的版本。举个例子,同时安装Appstore版本,隔夜AdHoc版本,和最近的开发版本。具体来说,当复现bug的时候,这将很好的方案。

因为每个环境都用的相同的App ID,这导致会覆盖之前安装的app,我们将在不同环境使用不同的App ID。这就是User-Defined设置的由来。

我们首先创建一个用户设置,这需要我们去target-build setting界面。然后打开Editor菜单,选择Add Build Setting-Add User-Defined Setting。现在,将新建的设置改名为CustomAppBundleId。接下来打开新的配置,显示不同的配置项。这里就是我们我们为不同环境设置不同值得地方。像下面设置不同的值:

//AdHoc

com.yourcompany.${PRODUCT_NAME:rfc1034identifier}.${CONFIGURATION}

//Debug

com.yourcompany.${PRODUCT_NAME:rfc1034identifier}.${CONFIGURATION}

//Release

com.yourcompany.${PRODUCT_NAME:rfc1034identifier}

Xcode会正确的方式解析使用的变量,并实时展示给你实际的值。正如你所见的,我们为Debug和AdHoc使用了配置后缀,但是Release没有。

我们还需要将用户的设置作为bundle id,可以在应用的info.plist文件中做到。(一般是应用名-info.plist)。默认的,它存在于Supporting Files组中。现在定位到Bundle identifier这个键值对,设置为${CustomAppBundleId}。

通过这些设置,你将可以安装多个版本的app。因为每个应用还是相同的名字和icon,所以还是很难区分不同的版本。接下来我们来探索为不同的环境设置不同的名字和icon。

为不同环境的App设置不同的名字


第一步,为了给每个环境版本的应用指定名字,我们还是通过添加User-Defined来实现。所以跟之前一样,在添加一个新的用户设置项,并改名为CustomProductName。现在,不同的configuration,设置了不同的名字。在我们示例应用中,如下:

//AdHoc

ConApp AH

//Debug

ConApp DE

//Release

${PRODUCT_NAME}

正如你所见,我们在Relase配置下使用了生产的名字,其他两个配置使用了自定义值。同样,回到info.plist文件,这次我们更改Bundle nameBundle display name,更改这两个键都为:${CustomProductName}。

现在运行程序,你将看到我们自定义的开发环境的版本App名称。然后让我们继续修改程序的icon。

为不同环境的App设置不同的icon


为不同环境App设置自己的icon,我们会用到程序默认生成的asset catalog。默认情况下,Xcode会把Image.xcassets放到app分组下。在image.xcassets中,你会看到AppIcon和LaunchImage。

我们假设你的Xcode版本高于5.0,低版本的没有asset系统。如果你还在基于老版本的xcode开发,你可以使用Info.plist文件来更改icon。查找一下Icon files这个key即可。

接下来,我们需要创建两个额外的Icon集合。点击Editor菜单中的New App Icon。重命名为:AppIcon-Debug,然后把对应的图标文件拖进指定位置。相同步骤新建一个AppIcon-AdHoc。最后一步,给默认的app icon集重命名为AppIcon-Release。

好了,现在我们已经将图标都放好了,接下来要告诉Xcode使用对应的图标集。打开targetBuild Settings,定位到Asset Catalog Compiler下的Asset Catalog Icon Set Name。现在对于每个configuration,如果你按照我们上述命名的话,我们改值为这样:

AppIcon-${CONFIGURATION}

这样就足够了。你的App已经对不同环境完全设置好了。唯一要做的就是测试一下。运行App,查看Debug configuration,用AdHoc Scheme打个AdHoc的包在指定机器上测试。最后使用普通的scheme创建一个Release版本。

除了发布App,你也可以在archives展示后通过organizer来确认。通常archives会在打包后自动打开。如果没有你可以通过菜单中的window打开。如果一切正常配置,app名称,id,icon都会在这里展示。

奖励:通过宏切换


为了对不同环境启用代码片段,你可以使用Preprocessor Macors。也许你已经猜到了,是在Build Setting中设置。打开build setting,定位到Apple LLVM 5.0 - Preprocessing下的Preprocessor Macors。对于每个环境添加如下代码:

CONFIGURATION_${CONFIGURATION}

然后,你可以使用这个宏来检测是什么环境,就像这样:

#if defined (CONFIGURATION_AdHoc) || defined (CONFIGURATION_Debug)

//Code placed here will only be compiled and thus

//included at runtime in AdHoc and Debug releases.

#endif


参考:


nilsou.com

stackoverflow


 尾巴:来自(oschina)


搞定了上面的设置,但是并没有完。如果你的项目使用了Podfile,pod install或者pod update时可能会有下面的提示:

今天在使用pod install的时候,出现了

[!] CocoaPods did not set the base configuration of your project because your project already has a custom config set. In order for CocoaPods integration to work at all, please either set the base configurations of the target `项目名` to `Pods/Target Support Files/Pods-项目名/Pods-项目名.release.xcconfig` or include the `Pods/Target Support Files/Pods-项目名/Pods-项目名.release.xcconfig` in your build configuration.


解决方案:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容