1 介绍
1.1 Target的理解
- 在Project 中,可以通过 Target 来指定一些指令、设置来生成Product(也就是说,Target就是生成对应Product的相关设置)。这些设置包含着 Info.plist , Build Setting ,Recource File等。
- Project 可以通过多个不同设置的 Target 生成不同的 Product,一个Target 对应生成一个 Product。
- Project 编译时可以设置两个编译版本,Debug、Release。所以Target里面会分Debug版本设置、Release版本设置。
1.2 Target的作用
- 单Target创建Project时,Xcode默认生成一个Target。
- 多Target
- 同个项目,运用在多现场,配置不同;
- 多个相似的APP,一些小模块不同;
2 多Target的使用步骤
2.1 创建
问:如何创建多个Target?
在使用Xcode创建一个新工程时,Xcode会默认在这个工程里面帮我们创建一个Target,并生成该Target关联的Info.plist文件,如下图。
创建新Target两种方式:
- 复制原先的Target
在原来Target上,点击右键,选择 Duplicate,便可复制生成新Target,并生成关联的Info.plist。如图。(本文举例采用这一种复制生成新Target)
- 重新创建新的Target
点击Xcode –> File –> New –> Target,创建新的Target。如图。
2.2 改名
由于复制生成的Target的名字不好区分识别,所以我们可以改动给Target重新命名。
如图,通过双击红框位置进行命名。
选择工程Target进行修改;
选择xcode左上角,选择Target处,Manage Schemes,进行修改;
2.3 关联Info文件
由于重新对Info.plist文件命名,会导致Target无法识别对应的Info.plist文件,所以在改名后,我们需要重新关联Info文件。
选择Target后,在 General –> Identity,点击重新选择关联Info文件。
3 多Target的考虑问题
考虑过使用多Target可以解决多现场等问题,但不同的Target之间配置、文件可能都不同,具体如何进行详细操作如下。
3.1 项目基础配置不同
项目的基础配置不同,如不同现场版本号不同、项目名称不同。这些基础配置,可以通过Product对应Target的Info.plist文件修改。
3.2 APP图标不同
不同现场APP图标不同,这里我们不用系统默认创建的 xcassets 文件,在各自的 Target 设置app icon处,重新创建 xcassets 文件。
考虑:
- 系统默认的 xcassets 文件可以放置共同类的图片;
- 满足不同 Product 对应 Icon 图片不同;
- 新建的 xcassets 文件,存放专属这个 Target 的图片;
取消使用系统默认的 xcassets 文件
重新创建 xcassets 文件
3.3 启动界面不同
使用系统默认生成的 launchScreen.storyboard 来设置启动界面,可这个 launchScreen.storyboard 没有帮我们关联所有的Target。需要自己设置这个 launchScreen.storyboard 的Target MemberShip。
点击 launchScreen.storyboard,查看Xcode右边,可看到一个Target MemberShip 的属性,选择关联哪个Target。
准备多张相同命名(如 launchImage.png)的启动界面图,分别添加到各自 Target 的 xcassets 文件中。
launchScreen.storyboard 的启动图片,选择这些启动图的名称(launchImage.png)即可。
3.4 业务逻辑需求不同
当多个现场的业务逻辑或者需求不同,则对应的Target实现的功能不同。这时我们分为两种情况,一种是不同Target需要不同的类文件实现不同的功能,一种是不同Target对应的图片资源不同。
3.4.1 类文件不同
类文件不同,例如A现场需要Person这个类来实现这个功能,而B现场需要Animal这个类来实现这个功能。
那么我们的做法是,创建对应的Person文件、Animal文件,让Person文件关联Target A(A现场),Animal文件关联Target B(B现场)。这里,我们称Person这个类是Target A 的专属类文件。
关联对应 Target 有两种情况,一种是新建文件时关联,一种是已建的文件设置关联。
- 新建文件关联:
- 已建文件关联:
在公共类调用不同Target对应专属类文件时,如何告诉编译器对应Target加载对应的专属类呢?
答案是:通过每个Target的预编译宏来区别。
首先,为每个Target设置本身的预编译宏。
在公共类使用预编译宏区分Target。
到这里,我们提出两个问题。
问:Target MemberShip的作用
答:一个文件属于哪一个Target。
例如,当我们要在某个target里面使用abc.png这张图片,不过没有将这张图片添加到 Target MemberShip中,就不能使用这张图片。
UIImageView *image = [[UIImageView alloc]initWithImage:[UIImage imageWithName:@"abc.png"]];
此时image会返回nil,因为找不到abc.png这张图片,虽然有存在工程里面,不过没有添加到Target 的MemberShip里面,所以Target是找不到的。
问:.m文件、XIB 可以添加为target menberShip,为何.h文件不需要添加呢?
答:因为可以关联target的文件需要满足两个条件:
- 可执行(可编译)文件,例如.m 和 库
- 被包括在包里面的文件,例如图片、XIB
而.h只有在编译时会使用,而在运行时是不需要的。(参考补充)
3.4.2 图片不同
例如,添加两张命名都为image.png的图片,到对应的Target MemberShip中,使用UIImageView加载image.png图片代码。
UIImageView *image = [[UIImageView alloc] initWithImage:[UIImage imageWithName:@"image.png"]];
此时,编译不同的Target,该ImageView会根据Target不同,加载不同的图片来显示。
4 多Target的优缺点
4.1 优点
- Target 之间可共用一些底层类、基础类,不必管理多个工程;
- Target 之间可有自己的资源、配置,避免多个现场下切换现场的资源、配置更改;
4.2 缺点
- 只适合于开发相似度大的APP、同个项目多现场;
- 在设置Target MemberShip 时,文件对应Target要分清,容易造成混乱;
补充说明
编译器到底对我们的代码做了什么
我们首先得明确编译过程主要包含一些什么步骤,具体步骤如下图
预处理阶段,对#define、#include、#import的展开,处理.pch文件。
将#后面的语句换成导入的文件。并且生成
中间文件
在 ViewController 这个类中,.h文件包含了 UIKit.h 和 CoreLocation.h 这些文件,.m文件中包含了.h文件和.m文件的全部代码。在预处理阶段,.m会生成中间文件,所谓中间文件就是上述这些文件的集合。
所以.h头文件不需要添加入Target的MemberShip中,因为在.m的实现文件中,会将.h文件包含到.m里面生成中间文件。
编译阶段,生成汇编语言
汇编阶段,根据汇编语言最终生成
目标对象文件
即.o文件。链接器链接阶段,将目标对象文件.o文件(在.o文件找symbol符号)与其他库链接在一起,生成
可执行文件
。- 动态链接
- 静态链接