利用多Target开发相似app
一、问题背景
开发一个与之前几乎一样的app。只是app名字等基本信息变更。
| 错误做法 | 正确做法 | ||
|---|---|---|---|
| 项目 | 再创建了新的项目 | 使用同一项目 | |
| 原因 | 极容易出现后来新开发的功能两个app都要支持 | 保证可共用到以后新开发的功能 |
下面我们开始介绍如何利用多Target开发相似app。
二、操作步骤
1、生成新的Target(这里推荐采用Duplicate方式,而不是File->New->Target)
1.1、Duplicate方法略。
1.2、Duplicate后,需要修改的东西
| 必选需修改项 | 操作方法 | 得到 |
|---|---|---|
| Info.plist | ①复制一份。 ②并重新为Target选择Info.plist ③跟新Info.plist中的名字、签名等 |
App1Info.plist、App2Info.plist |
| Scheme | Manager Scheme -> 双击重命名 | 新的App2Scheme |
| 证书&描述文件 | 更具新的BundleId,添加证书&描述文件 | 真机编译通过 |
特别注意:add Info.plist等文件的时候,一定要注意选择对应的Target。不多多勾选☑️,也不要少勾选。
1.3、其他APP定制项更改
| 可选修改项 | 操作方法 | 得到 |
|---|---|---|
| icon | 修改InfoPlist | 新APP的Icon |
| 名字 | 修改InfoPlist | 新APP的名字 |
2、Target区分
需求背景:有些共用的文件在不同的Target下是有细微不同的,那么我们在具体实现的时候就需要作出区分。
2.1、Objective-C、C、C++的LLVM预处理宏的添加
Objective-C、C、C++的LLVM预处理宏在Preprocessor Macros处定义。如图创建工程时已经默认创建好了在Debug时定义DEBUG=1 宏标记。
2.2、Swift
因为Swift 中没有宏定义的概念,因此我们不能使用 #ifdef 的方法来检查某个符号是否经过宏定义。
在项目的 Build Settings 中,找到 Swift Compiler - Custom Flags,并在其中的 Other Swift Flags
为APP1加上 -D APPTARGET1 就可以了;为APP2加上 -D APPTARGET2 就可以了;
其他参考文章:https://blog.csdn.net/kaiyuanheshang/article/details/78862382
解决办法:这里解决的方法是针对不同的Target在Preprocessor Macros中定义宏,如添加TargetTYPE。
- 在Preprocessor Macros中添加
TARGETTYPE后

Target代码区分需用到的知识:
| 含义 | 示例 | |
|---|---|---|
#if |
既关心宏是否定义,又关心宏的逻辑的真假 | |
#ifdef#ifndef |
仅仅关心宏是否被定义,不关心宏的逻辑真假 |
代码区分如下:
1 | #if TARGETTYPE == 0 |
至此,你直接编译,发现”好像”完成了。实际上如果你的项目没有使用POD的,确实是到此就完成了 。

下面我们额外补充,当你的项目有使用POD的时候,你还需要处理的东西。
3、Pod修改
在上述中,你可能发现好像我使用了POD的但是依然正确编译通过啊。
是的,是通过了,但是这是假象。或者准确的说,当你下次使用POD相关命令,如pod install的时候,你会发现之前的项目编译不通过了。
所以,你需要修改PodFile,并重新pod install。PodFile的修改方法如下:
1 | target 'APP1' do |
- 修改方式1:
1 | There are no targets called "APPCommon" in any Xcode projects |
- 修改方式2:
1 | # 共用的第三方库 |
最后修改完后,重新pod install后即可。

4、脚本打包时候,因为多Target后旧的libPods-xxx(Framework)忘删除引起的问题
多Target后旧的libPods-xxx引起的问题

多Target后旧的libPods-xxx的问题解决否的判断

三、Swift中的条件编译
在C 系语言中,我们可以通过预处理宏定义一些参数,使用#if或者#ifdef编译条件分支来控制哪些代码需要编译,而哪些代码不需要。但是在swift中没有宏定义的概念,虽然不能使用 #ifdef 的方法来检查某个符号是否经过宏定义,但是可以支持“#if/#else/#endif”语句。