首页 Xcode 多个 target 的管理
文章
取消

Xcode 多个 target 的管理

前言

工作中总会遇到一些这样那样的需求, 比如需要打包一个 Appstore版 + 企业版. 但是却总要手动修改 Bundle Id 等等的这些信息, 比较麻烦(当然马甲包也可以这么搞),最重要的万一某一个宏忘记手动切换了,但是测试又没测出来就上架了 Appstore ,那问题就大了. 于是就有了这篇文章.

简介

这里用到的方法主要是对 target 进行复制, 并且使用脚本自动化的修改条件宏来通过 条件编译 达到我们的目的.

复制 target

右键点击需要复制的 target, 点击 Duplicate.就会复制出一份新的 target.

此时选择新的 target 编译运行正常情况是能够直接通过的.

Target 的配置

复制一些需要区别配置或者不同代码的文件.

  • AppDelegate 需要配置一些第三方的 key.比如友盟 个推等.为了避免麻烦我直接拿出来分别写
  • Assets.xcassets 里面有不同的图片资源, 也需要复制一份.
  • Info.plist 工程一些配置信息.
  • main.m 里面需要配置 AppDelegate .(下面会讲)
  • Main.Storyboard
  • LaunchScreen.storyboard

根据自身需求决定哪些文件需要 copy 新的.

文件配置

因为同一个工程内部不能有 同名的类 , 所以复制出来的 AppDelegate 需要修改一下名称 比如 NewAppDelegate.这里就用到了 main.m. 需要在 main.m 中做如下修改:

1
2
3
4
5
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([NewAppDelegate class]));
    }
}
类/文件的归属配置:

这里是重点,配置不对将会很麻烦,甚至导致工程跑步起来. 此处以 main.m 为例: 选中 main.m 文件之后, Xcode 右侧区域中会出现 Target Membership 栏目. 如图所示: 此时选中的 target 就是该文件的归属, 通俗点就是在哪个 target 里面生效. 同一个文件也可以同时归属多个 target.

大部分文件都可以通过这种方式来设置. 比如: class, xib, storyboard, xcassets 等.

如果编译时候某个类找不到了,就可以在这个地方把对应的 target 勾选中就可以了.

条件宏的自动化

分别创建宏的 头文件 Config.h 和 脚本文件 Config.sh.

配置脚本

Build Phases 中点击左上角 + 新建一个 Run Script.

在如图的位置写上执行脚本的路径

1
2
// $PROJECT_DIR 是工程根目录, 根据情况来写
$PROJECT_DIR/Config/Config.sh

脚本

Config.sh 中写入如下脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 开关配置的头文件路径, 根据情况来
HeaderPath=$SRCROOT/Config/ProjectConfig.h
// 通过判断 Bundle Id 来区分当前编译的是哪个 Target
if [ $PRODUCT_BUNDLE_IDENTIFIER == "com.example.app1" ]; then
    // 把开关宏的值输入到配置文件内
    echo "#define TARGET_SWITCH 0" '// app1'  > $HeaderPath
elif [ $PRODUCT_BUNDLE_IDENTIFIER == "com.example.app2" ]; then
    echo "#define TARGET_SWITCH 1" '// app2' > $HeaderPath
elif [ $PRODUCT_BUNDLE_IDENTIFIER == "com.example.app3" ]; then
    echo "#define TARGET_SWITCH 2" '// app2' > $HeaderPath
else
    echo "// 未配置" > $HeaderPath
fi

此时选择不同的 target , 不管Run 还是 Build, 在 Config.h 中就会自动在

1
2
3
4
#define TARGET_SWITCH 0
#define TARGET_SWITCH 1
...
#define TARGET_SWITCH n

之间自动切换了.

脚本的原理就是判断不同 target 的 bundle id 在 Config.h 写入不同的宏. 关于脚本怎么写, 可以自己学习一下 Shell

结束

到此, 你就可以根据 TARGET_SWITCH 的值来对不同的 target 区别编译不同的代码了.

补充: 虽然这个比较方便,但是却有可能因为某一个 target 的代码无法编译通过而导致其他的 target 也无法编译通过,因此要做好不同 target 代码的屏蔽.

本文由作者按照 CC BY 4.0 进行授权