前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >工程管理篇 | 多Targets

工程管理篇 | 多Targets

作者头像
進无尽
发布2018-09-12 18:21:21
1K0
发布2018-09-12 18:21:21
举报
文章被收录于专栏:進无尽的文章進无尽的文章
前言

很多时候,工程管理是一个很实际的技能,我们在实际开发中普遍有很多环境:测试环境、开发环境、生产环境等。还有可能遇到需要创建两个很多内容相同,部分功能不同的工程。

如果需要切换环境发版本的话,你可以手动注册修改代码实现(如果你喜欢这样的话,也就不需要继续看本文了),不是说这样很low,而是当不同环境的差异比较多的话,这种手动管理工程版本的方法笨拙而且容易出错。

创建两个很多内容相同,部分功能不同的工程,你可以选择拷贝,修改,保存,成为两个工程。当然还有另一种优雅的姿势。

这个姿势挺累的

这些问题都可以通过设置多个 Targets 来解决。

其它知识补充

workspace 、Project、target、 Scheme 的关系和简介

workspace 是Xcode的一种文件,用来管理工程和里面的文件,一个workspace可以包含若干个工程 project 里面包含了所有的源文件,资源文件和构建一个或者多个product的信息。project利用他们去编译我们所需的product,也帮我们组织它们之间的关系。一个project可以包含一个或者多个target。 target 每个target都继承了project的默认设置,每个target可以通过重新设置target的编译选项来定义自己的特殊编译选项。一个target对应于一个product(产品)scheme 定义了编译集合中的若干target,编译时的一些设置以及要执行的测试集合。我们可以定义多个scheme对应一个target

关于Target

相信很多人都注意到XCode中, 有个Target的概念.那么这个Target到底是什么呢?

Apple的人是这样说的:“ Targets that define the products to build. A target organizes the files and instructions needed to build a product into a sequence of build actions that can be taken.”

简单的理解的话, 可以认为一个target对应一个新的product(基于同一份代码的情况下). 但都一份代码了, 弄个新product做什么呢 ?

其实这不是单纯的瞎折腾, 虽然代码是同一份, 但编译设置(比如编译条件), 以及包含的资源文件却可以有很大的差别. 于是即使同一份代码, 产出的product也可能大不相同.

Targets之间, 什么相同, 什么不同!

既然是利用同一份代码产出不同的product, 那么到底不同Target之间存在着什么样的差异呢? 要解释这个问题, 我们就要来看看一个Target指定了哪些内容.

从XCode左侧的列表中, 我们可以看到一个Target包含了Copy Bundle Resources, Compile Sources, Link Binary With Libraries. 其中

  • Copy Bundle Resources 是指生成的product的.app内将包含哪些资源文件
  • Compile Sources 是指将有哪些源代码被编译
  • Link Binary With Libraries 是指编译过程中会引用哪些库文件

Paste_Image.png

通过Copy Bundle Resources中内容的不同设置, 我们可以让不同的product包含不同的资源, 包括程序的主图标等, 而不是把XCode的工程中列出的资源一股脑的包含进去。

而这还不是一个target所指定的全部内容. 每个target可以使用一个独立, 不同的Info.plist文件。

我们都知道, 这个Info.plist文件内定义了一个iPhone项目的很多关键性内容, 比如程序名称, 最终生成product的全局唯一id等等。

而且不同的target还可以定义完整的差异化的编译设置, 从简单的调整优化选项, 到增加条件编译所使用的编译条件, 以至于所使用的base SDK都可以差异化指定.

两种添加Targets的方式
拷贝原有的Target

项目里面创建了多个target(分别是:生产环境、测试环境、开发环境),每个target对应一个环境,并配置不同的info.plist文件,这样做的好处是不用开发人员每次都要去手动开启/注释某些代码去发布,而是先配置好,到时候直接切换target就可以打包上线了切换一下target,运行一下,就是一个新项目。

第一步:

弹出来的的页面是:一般选择中间那个选项 Duplicate only,如果有pad,则选择最后一个

第二步:

第三步:(这里不要忘了把你原来的Info.plist文件也勾选对了)

第四五六七步:

通过在不同的Targets 预定义宏(Build Setting–>Preprocessor Macros)区分不同的工程环境

这个宏是一个全局宏,在所有/整个工程的代码中都是有效的,我们可以在这里添加上环境与处理的宏(例如:WD_Environment_Mode,这个是随便自己取的)

代码语言:javascript
复制
#然后在.pch文件中
/**
WD_Environment_Mode
0:生产环境
1:测试环境
2:开发环境
*/
#ifdef    WD_Environment_Mode
#if       WD_Environment_Mode == 0
#define    WDAPIServerUrl   @""
#define    JSPatchAppKey     @""

#elif      WD_Environment_Mode == 1
#define    WDAPIServerUrl @""
#define    JSPatchAppKey  @""

#elif    WD_Environment_Mode == 2
#defineWDAPIServerUrl @""
#defineJSPatchAppKey  @""
#else
#warning"未匹配环境"
#endif

*************************************** 更多关于 预定义宏的使用

而 Xcode 在產生新的 project 時,會自動在 Debug scheme 裡面加入 DEBUG=1 這個 Preprocessor Macro. 因此可以使用 DEBUG 這個 preprocessor macro 來區分 debug 和 release mode.

代码语言:javascript
复制
  ViewController.m
  ...
  #ifdef DEBUG
      [self.hintLabel setText:@"Debug mode"];
  #else
      [self.hintLabel setText:@"Release mode"];
  #endif
  ...

如果你不喜欢、不习惯这样的代码写法 可以在 PrefixHeader.pch 裡面加入以下的片段:

代码语言:javascript
复制
  PrefixHeader.pch

  #ifdef DEBUG
  #define debug_only YES
  #else
  #define debug_only NO
  #endif

  ViewController.m
   ...
  if(debug_only){
      [self.hintLabel setText:@"Debug mode"];
  } else {
      [self.hintLabel setText:@"Release mode"];
  }
  ...

就可以在所有的 source code 都直接用 if(debug_only){ ... } 來將 debug 時才會用到的程式片段包起來了。这是你最熟悉的方式是吧.

****************************************

总结一下,上面这种复制 target的方式比较适合不同的环境需要用到的变量值不同,也就是通过不同的 Target里面的 全局宏的值来做判断依据的,但是整套工程还是只有一套代码,相当于做了条件编译。

生成一个新的target,一定会与原target有区别,这里可以定义预编译宏,来区分两个版本的不同代码,预编译宏可以在Build Settings中Preprocessor Macros定义,比如在我们新建的target B中定义预编译宏MACRO,然后在代码中通过

代码语言:javascript
复制
  #if defined (MACRO)
       //target  B需要执行的代码
  #else
       //target A需要执行的代码
  #endif

来区分

创建全新的target

有的时候,我们创建两个很多内容相同,部分功能不同的工程,你可以选择拷贝,修改,保存,成为两个工程。当然你也可以利用 多个 Target实现。

但是有时候,两个版本里面的资源是冲突的,不能同时导入到一个target,上面我们通过复制 Target实现的其实是条件编译,并不是真正的新Target。下面的方式就能解决上面提到的冲突的问题。

最赞的是,这种方式即可以解决导入资源冲突的问题,又可以把公用的部分拿出来,供两个Target使用,真正做到了:只修改或者创建不同的功能,公用相同的功能。

Paste_Image.png

会出现一个弹框,向下滚动,选择Single View Application-->Next-->Produce Name -->Finish

Paste_Image.png

但是这样生成出的Target几乎是空的. Copy Bundle Resources, Compile Sources, Link Binary With Libraries里面都没有任何内容. 编译设置也是完全原始的状态。等于是一个新的小工程。

图中 Comment中的文件是俩个 Target的公用部分,可以供俩个Target使用,实现了工程中创建小的新的工程的效果。


本文参考文章 手把手教你给一个iOS app配置多个环境变量 使用 Preprocessor Macros 區分 release 和 debug 版本 如何在iOS项目中创建多个target

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.03.10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 其它知识补充
    • 关于Target
    • 两种添加Targets的方式
      • 拷贝原有的Target
      • 创建全新的target
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档