我们在开发中经常会遇到一个 APP 存在多种渠道版本,例如:debug版App Store版testflight版$299企业版 等等。
他们之间可能会存在不同的名字、应用图标、Bundle Identifier、些许功能差异等。

说明

旧文章写于 2017年,与新版 Xcode 存在较大操作差异,现本文已重构并以最新版 Xcode13 作为样例进行演示。
使用 Gank.io 项目进行演示。

创建新的 target

1、选中项目-TARGETS-Gank.io
2、右键 Gank.io-Duplicate

https://img.wangquanwei.com/wp-content/uploads/2017/04/C5615137-01B4-4912-89D2-C37367C4D7E1.jpeg

3、出现弹窗提示选择 Duplicate Only,就会生成新的 Target Gank.io copyGank.io copy-Info.plist 文件

The selected target is an iPhone target. Would you like to duplicate the iPhone target and transition the new target for running on iPad?

4、单击 Gank.io copy 可以编辑名称,用以区分渠道,这里改为 Gank.io Inhouse
5、修改完 Target 名称会发现两处显示不一致,重启编译器即可解决

https://img.wangquanwei.com/wp-content/uploads/2017/04/EAB1985A0294DE16D88762A751E92142.jpg

6、修改 Gank.io copy-Info.plist 文件名,这里改为 Gank.io Inhouse-Info.plist 改完后,还需要关联一下,否则运行报错

error: Build input file cannot be found: '/Users/wangquanwei/Documents/data/Gank.io/Gank.io copy-Info.plist' (in target 'Gank.io Inhouse' from project 'Gank.io')

7、关联 Gank.io Inhouse-Info.plist 文件
方式一: Xcode13 (其他版本不晓得) 中未关联 Gank.io Inhouse-Info.plist,Identity 会有 Choose Info.plist File… 按钮(重启编译器后出现)点击可以选择 Info.plist 文件(选完编译器不会刷新,需要切换下 Target 才可正常显示)。

https://img.wangquanwei.com/wp-content/uploads/2017/04/9F5B1933-D91A-4580-B20D-5065C76A3270.jpeg

方式二: 选中Target-Build Settings-All-搜索 info.plist File
输入 Gank.io Inhouse-Info.plist (这里只做演示)

https://img.wangquanwei.com/wp-content/uploads/2017/04/82C9EA60-5B7B-4399-AF9F-147EB509114D.jpeg

不同的 Target 显示不同的 app 名字

选择 Gank.io Inhouse (这里只做演示) – Display Name 直接改

https://img.wangquanwei.com/wp-content/uploads/2017/04/1C140BC90F8D3DE7CBF71CD569066F8A.jpg

不同的 Target 显示不同的图标

1、创建新的 App Icon

Asset-右键-iOS-New iOS App Icon

2、将会得到 AppIcon-1,将其改名为 InhouseAppIcon (这里只做演示)
3、在 TARGETS-Gank.io Inhouse-Build Settings-搜索 Primary App Icon Set Name 把值改为 InhouseAppIcon (这里只做演示)

https://img.wangquanwei.com/wp-content/uploads/2017/04/A3A7D10B-693A-44F7-81CD-F80ADDDDE9AA.jpeg

不同的 Target 显示不同的启动页

1、创建新的 Launch Screen 并命名为 InhouseLaunchScreen (这里只做演示)
2、在 Gank.io Inhouse (这里只做演示)-Info-Launch screen interface file base name 里填入 InhouseLaunchScreen (这里只做演示)

不同的 Target 使用不同的代码

根据不同的语言配置相应的宏
Objective-c
Build Settings-Preprocessor Macros-输入 GankIoInhouse=1(这里只是演示)

https://img.wangquanwei.com/wp-content/uploads/2017/04/4618DDAD-564D-444B-90B9-4289D60C050B.jpeg

Swift:
Build Settings-Swift Compiler Custom Flags-Other Swift Flags-输入 -D GankIoInhouse(这里只是演示)

// Swift要注意 使用自定义环境变量前面要加 -D
// -D GankIoInhouse 中间是有空格的切记!!!
-D GankIoInhouse

https://img.wangquanwei.com/wp-content/uploads/2017/04/914379A4-2C1F-4A07-AD41-9550F153AF2E.jpeg

使用方法,在差异化的地方使用宏做判断

#ifdef GankIoInhouse
    NSLog(@"GankIoInhouse");
#else
    NSLog(@"GankIo");
#endif

关于 New Target ‘xxx-Swift.h’ file not found

因为项目配置中桥接文件的名称和 Target 名称不一致,所以导致桥接头文件找不到。

https://img.wangquanwei.com/wp-content/uploads/2017/04/D39DA080-BC4F-486D-9399-0D3518D6AA65.jpeg

这个时候我们检查 Build Settings 中的 Objecttive-C Generated Interface Header Name 选项是否和我们 import 的名称一样,不一样的话改成 import 一样或者使用 __has_include 做区分

#if __has_include("Gank_io-Swift.h")
#import "Gank_io-Swift.h"
#else
#import "Gank_io_Inhouse-Swift.h"
#endif