本文原地址:http://www.appcoda.com/using-xcode-targets/

在开始此教程之前,我们假设你已经完成了应用程序的开发和测试,现在准备提交生产发布。问题是,某些web服务URLs指向测试服务器,而API keys则为测试环境而配置。在提交应用程序给苹果审核之前,你需要修改所有这些API keys和URLs以适应生产环境。这很正常,对吧?但是,除了将这些值在开发和生产环境之间来回更改,是否存在更好的方法来管理开发和生产版本呢?

下面开始我们的教程!

首先,你们中的一些人可能想知道为什么在应用开发时,需要使用两个单独的数据库和环境。

原因是,随着持续不断的构建新的功能或者开发应用,你想确保开发版本和现有版本相互区分。标准软件开发过程旨在针对软件(在我们的案例中,即为iphone应用)的不同版本,使用不同的环境。开发版本软件通常使用一个不同于生产版本的数据库(或者其他系统,比如分析)。这就是为什么我们应该在不同的环境中使用不同的服务器和数据库。开发人员通常在测试期间使用虚拟图像和数据。在测试或开发环境中,通常会使用一些测试数据,比如”test comment“,”argharghargh“和”one more test comment“。很明显,你可不希望真实用户看到这样的消息。如果你的应用使用了分析系统,你可能在测试阶段发送成千上万的事件。同样,你不想在同一个数据库中混合测试数据和生产数据。这就是为什么总是推荐使用相互独立的开发和生产环境。

在使用两个独立的环境时,你的应用需要一种方法来找出它应该连接的环境。一个常用的方法实在主app delegate中定义一个全局变量,将应用初始化为开发或生产模式。

这种方法需要你在每次切换环境时,改变全局变量。尽管还算快速和方便,这种方法也有一些重大的限制。首先,因为我们在开发和生产环境中使用同一个budle ID,你不能在同一个设备上安装两个应用版本。当你想在同一台设备上测试应用的开发版本,但目前仍在使用应用的生产版本时,就非常不方便。此外,这种方法可能会意外地将应用的开发版本发布到 应用商店。如果你亡了改变单一的全局变量,你就会发布错误的应用程序。笔者记得有一次在应用提交之前,忘记改变全局变量,用户获得的就是应用的开发版本。那简直就是一场灾难。

在本文中,笔者将向你展示一个更好的方法,来区分开发和生产版本。

具体来说,我们将在Xcode中创建一个开发Target。此方法同时适用于新的,和现有的大型项目,所以你可以使用一个现有的应用程序,来学习本教程。

通过使用这种方法,应用的生产和开发版本将具有相同的基础代码,但是可以有不同的图标,bundle ID,并只指向不同的数据库。发布和提交过程非常简单。最重要的是,测试人员和经理可以在同一设备上,安装应用程序的两个版本,所以他们完全清楚正在测试的是哪个版本。

如何创建一个新的Target

如何在Xcode中创建一个开发Target?笔者将使用自己的模板项目”todo“,逐步演示开发过程。你可以使用自己的项目,按部就班即可。

  1.在Project Navigator面板中找到项目设置。在tragets区域,右键单击现有target,并选择Duplicate复制现有的target。

  2.Xcode会问你,新target是否为ipad而开发。对于本教程,我们选择”Duplicate Only“。

Note:if your project supports universal devices,Xcode will not promt the above message .注意:如果你的项目支持通用设备,Xcode则不会提示上述消息。

  3.现在,我们有了一个新的target,和一个新的构建scheme,名为todo copy。让我们对它重命名,使其容易理解。

    ·在TARGETS列表中,选择新的target。按enter键来编辑文本,选择一个合适的名字。笔者更喜欢”todo Dev“.可以自由选择任何喜欢的名字。

    ·接下来,选择”Manage Schemes...“,选择你在步骤1中创建的新scheme,按下”Enter“。使cheme名称和显得target名称一样(也就是你为新的target选择的名称。)

  4.步骤4是可选的,但强烈推荐使用。如果你想简单的区分开发和生产版本,你应该为每个版本使用单独的图标和启动屏幕。这将使你的测试人员很清楚地知道他们正在使用哪个应用,防止你发布开发版本的应用。

选择Assets.xcassets,并添加一个新的图标。右击icon>App Icon & Launch Images > New iOS  APP icon。将新图标重命名为”AppIcon-Dev“,然后添加自己的图片。

5.现在回到项目设置,选择你的开发target,并更改bundle identifier。比如,你可以在原ID上简单添加”Dev“。如果你执行了步骤4,确保你把应用图标设置为上一步冲创建的那个。

6.Xcode将为你的target自动添加plist文件(比如todo copy-info.plist),你可以在项目的根目录中找到它。将它从”copy“重命名为”Dev“,并将其保存在原来的plist文件下。这样就能方便管理文件。

7.现在打开开发target的”Build Settings“,滚动到”Packaging“,将值更改为开发Plist文件(比如todo Dev.plist)

8.最后,我们将为生产和开发targets配置一个预处理宏/编译器标记。这样之后就可以在代码中使用标记来检测正在运行的是应用程序的哪个版本。

对于Objective - C项目,选择Build Settings,滚动到Apple LLVM 7.0 - Preprocessing。展开Preprocessor Macors,添加Debug和Release fields变量。对于开发target(比如todo Dev),将值设置为DEVELOPMENT = 1.换句话说,将值设置为 DEVELOPMENT = 0 来表示生产版本。

对于Swift项目,编译器不再支持预处理器指令。相反,它使用编译时属性和构建配置。添加一个标识,来标示开发版本,选择开发target。选择Build Settings和向下滚动到Swift Compiler - Custom Flags部分。将值设置为-DEVELOPMENT来标示target为开发版本。

现在,你已经创建和配置完成开发target,下一步是什么?

使用target和宏

通过配置宏DEV_VERSION,可以在代码中使用它,为项目执行动态编译。下面是一个简单例子:

Object-C

#if DEVELOPMENT
#define SERVER_URL @"http://dev.server.com/api/"
#define API_TOKEN @"DI2023409jf90ew"
#else
#define SERVER_URL @"http://prod.server.com/api/"
#define API_TOKEN @"71a629j0f090232"
#endif
在Objective - C中,你可以使用#if检查DEVELOPMENT的情况,并相应地设置URLs/API keys。 注意:通常情况下,你应该把上面的代码放入app delegate。但实际上取决于你在哪里初始化应用的设置。 现在,当你选择”todo Dev“scheme,并运行这个项目,你将自动创建开发版本,服务器配置设置为开发环境。现在可以向TestFlight或HockeyApp上传开发版本,供测试人员和管理人员进行测试。
之后,如果你需要创建一个生产版本,简单地选择”todo“scheme即可。不需要任何代码更改。 管理多个targets的一些提示
1.将新文件添加到项目时,别忘了同时选择两个targets,保持代码在两个版本的同步。

2.如果用cocoapods,别忘了将新的target添加到podfile。可以使用link_with来指定多个targets。podfile文件内容:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '7.0'
workspace 'todo'
link_with 'todo', 'todo Dev'
pod 'Mixpanel'
pod 'AFNetworking'
 

[HMLY]3.如何使用Xcode Targets管理开发和生产版本?的更多相关文章

  1. 如何使用 Xcode Targets 管理开发和生产版本?

    在开始此教程之前,我们假设你已经完成了应用程序的开发和测试,现在准备提交生产发布.问题是,某些 Web 服务 URLs 指向测试服务器,而 API keys 则为测试环境而配置.在提交应用程序给苹果审 ...

  2. 如何使用Xcode的Targets来管理开发和生产版本的构建

    如何使用Xcode的Targets来管理开发和生产版本的构建 想象一下,你已经完成了应用程序的开发和测试,现在准备提交正式版本.问题是,一些web服务的url指向了测试服务器,同时API密钥被配置用于 ...

  3. 使用Xcode的Targets来管理开发和生产版本的构建

    如何创建一个新的Target 如何在Xcode中创建一个开发的target?我使用示例项目“todo”引导您一步一步完成整个过程..您也可以使用自己的项目并按照步骤: 1. 在项目的导航面板进入项目设 ...

  4. Xcode模拟器不显示SDK版本,反而显示设备ID的解决办法

    今天在应用程序中修改了Xcode app 的名称,结果导致Xcode模拟器不显示SDK版本,反而显示设备ID了,感觉特别的忧伤......如图: 进到Xcode->window->Devi ...

  5. xcode7.3 升级 xcode8.0 后权限设置问题(升级xcode 8.0 后构建版本不显示问题)

    xcode7.3 升级 xcode8.0 后权限设置问题(升级xcode 8.0 后构建版本不显示问题) 前两天为了适配 iOS10 的系统 我将xcode 7.3 升级到了 xcode 8.0 但是 ...

  6. iOS Mobile Development: Using Xcode Targets to Reuse the Code 使用xcode targets来实现代码复用

    In the context of iOS mobile app development, a clone is simply an app that is based off another mob ...

  7. xcode 怎么样在发布release版本的时候 不输出log

    我们平时在开发应用的时候,经常会用到 NSLog 来调试我们的程序,而随着项目越来越大,这些用于调试的日志输出就会变得很难管理. 发布正式版的时候一定要屏蔽掉所有后台输出,因为这些输出还是比较消耗系统 ...

  8. Xcode 向6.0以后版本添加iOS开发空白模板

    打开finder,找到应用程序,找到xcode 右键显示包内容.按照如下目录进行查找:Contents ▸ Developer ▸ Platforms ▸ iPhoneOS.platform ▸ De ...

  9. 查看Xcode所使用Swift的版本

    查看Swift版本 $ xcrun swift -version 查看Xcode位置 $ xcrun --find swift 参考链接:http://stackoverflow.com/questi ...

随机推荐

  1. iOS制作Static Library(静态库),实现多工程的连编

    在iOS开发中,我们会发现一些偏底层或基础代码是直接可以复用的,当我们换一个项目,改变的只需要是偏上层的业务逻辑代码,所以我们可以把这部分基础代码制作为一个静态库static library,并不断扩 ...

  2. 分析Sizzle引擎

    jQuery 2.0.3 源码分析Sizzle引擎 - 打造高效查询 为什么Sizzle很高效? 首先,从处理流程上理解,它总是先使用最高效的原生方法来做处理 HTML文档一共有这么四个API: ge ...

  3. 由ASP.NET所谓前台调用后台、后台调用前台想到HTTP

    由ASP.NET所谓前台调用后台.后台调用前台想到HTTP 在由ASP.NET所谓前台调用后台.后台调用前台想到HTTP——理论篇中描述了一下ASP.NET新手的三个问题及相关的HTTP协议内容,在由 ...

  4. JS获取图片实际宽高

    JS获取图片实际宽高,以及根据图片大小进行自适应 <img src="http://xxx.jpg" id="imgs" onload="ada ...

  5. 启动mysql错误解决方案,学会查看错误日志:mysql.sock丢失,mysqld_safe启动报错

    本人还是个菜鸟,下面是我的经验之谈,能解决一些问题,有不对的地方,敬请斧正. 我的是CentOS6.3+MySQL5.1.57. 重启了一次服务器后,使用> mysql -u root -p登陆 ...

  6. MingQQ v1.0高仿版开源了,使用WebQQ协议实现了QQ客户端基本的聊天功能...

    MingQQ v1.0高仿版开源了,使用WebQQ协议实现了QQ客户端基本的聊天功能... MingQQ目前支持的功能如下:1.支持普通方式登录.验证码方式登录.注销.保持在线.改变在线状态.2.支持 ...

  7. 用Linux命令行实现删除和复制指定类型的文件

    (一)Linux 删除当前目录及子目录中所有某种类型的文件 方法1 : 此方法不能处理目录中带空格的那些. rm -rf `find . -name "*.example"` Li ...

  8. POJ 3900 The Robbery

    大意:和背包的问题相似,第 i 个箱子有 i 颗钻石.钻石的重量,价值给出.然后再M的重量下背尽量多价值的钻石. 思路:直接暴搜然后剪枝.因为数据范围的原因无法用DP. #include <cs ...

  9. [置顶] NS2中对TCP数据包和ACK包的TCP Sink类的主要实现代码详尽剖析--吐血放送

    NS2中对TCP数据包和ACK包的TCP Sink类的主要实现代码详尽剖析,限于个人水平,如有错误请留言指出! TcpSink类的recv()方法: void TcpSink::recv(Packet ...

  10. 巧用final

    1.final可以修饰函数的参数,以防止函数内部随意篡改不允许修改的参数. 2.在函数内部,把函数的局部变量声明为final类型,可以检查在函数内部它们是否的确只被赋值一次.