我们在iOS开发中可能会遇到同时开发多个类似项目的情况。这些项目大同小异,有诸多代码可以共用,如果每个项目都分别开发,这在后期的迭代中会十分繁琐。为了解决这个问题,使用多Target开发是一种比较好的选择,本文就这一技术实现进行简要总结。
一、理解项目中的Porject与Target
使用Xcode来开发项目,其中的Project是一个整体项目相当于一个仓库,包括了所有的代码和资源文件。而Target相当于一个具体的产品,包含了对于代码,资源文件的具体使用规则和配置。一个Project可以包含多个Target,也就是说通过不同Target我们可以生成不同的APP。
二、多Target开发项目的实践步骤
使用多Target来创建项目,就以我当前正在开发的亲戚买房APP为例。需求是这样的:亲戚买房是一个为买房人提供砍价服务的APP,APP的用户需要区分为用户,专家和砍价师三个用户群体。所以这里以Customer,Consul,Bargain三个Target来开发应用
以QQMF(亲戚买房)为名创建一个新的工程如下:
创建三种Target
创建新Target的方式有两种:
第一种:依次选择File->New->Target,然后选择一个模板(通常是Single View App)来创建。只是这样创建的target带有Appdelegate和main等文件,在这里并不会用到这些文件,所以我们采用第二种方式创建。
第二种:
在Targets中点击已有的Target,右键选择Duplicate可以复制生成一个copy的新Target,并且在文件目录中生成对应的copy-Info.plist文件。这样生成的target与被拷贝的target相似度很大,减少了过多的修改。通常为了减少后期的修改,我们也会首先在原有的Target中修改一些配置之后再Duplicate。
执行了Duplicate操作之后的效果如下:
1.修改Targe和plist文件的名称为自己需要的名称
在Target里可以直接修改Target的名称,在文件目录下也可以直接修改plist文件的名称。如果我们不想文件结构那么乱,也可以像其他文件一样移动plist文件的位置并重新引用到工程中,如下:
特别注意:我们在移动文件的时候可能需要重新引用文件到工程中,此时add文件的时候一定要注意选择Target,如果是共用文件一定要勾选对应的Target,类似AppDelegate这样文件的操作如下:
2.修改Xcode左上角的Target名称
选中Xcode左上角的创建工程时的Target(QQMF),选择Manage schemes
在如下的schemes中修改Target的名称,这里也可以删除多余的最初的QQMF
特别说明:QQMF是我们创建工程自带的Target,其实也可以修改它的名字以供自定义使用,而这里我们是直接删掉了它,这样之后,项目自带的info.plist也是没用的了,也可以删掉。
1.设置Target与plist文件对应
切换到Target目录下,我们可以在这里删掉用不到的QQMF,选择其中一个Target之后并选择general,然后可以看到每个Target的右侧都有对应的choose info.plist file选项,点击可以选择与Target对应的plist文件。这也就相当于不同的Target项目对应了不同的plist配置。
2.为每个Target设置Display Name,Bundle Identifier等信息
点击Target->选择General,我们分别设置不同项目的名称和BundleID信息,以及证书等
同一份代码区分不同Target的操作
使用多Target是为了共用一部分代码,但是有些共用的文件在不同的Target下是有细微不同的,那么我们在具体实现的时候就需要作出区分。这里解决的方法是针对不同的Target定义宏。
首先选择一个Target,如Customer,依次选择Build Settings ->搜索PreprocessorMacros, 在找到PreprocessorMacros之后,我们分别在Debug和Release中设置TargetType=1如下图进行设置:
其他的Target也是同样的设置方式,只是要区分TargetType的值,分别是2,3(TargetType及其值都是自定义的)。然后就是在代码中的使用如下图,分别选择Xcode左上角不同的Target运行,查看控制台验证是否成功。
1.解决使用Cocoapods的问题
因为存在多个Target,我们需要区别的设置不同target需要的第三方库,如下图。这里可能出现的问题是如果有很多类似AFNetworking这样的被多个Target需要的类库,我们在删除和增加的时候就会频繁的操作而且会代码冗余。
解决上述问题的比较优雅的做法是如下:
三、遇到的问题
问题:invalid token at start of a preprocessor expression
原因:这是我在pch文件中判断target类型出现的错误,这句话的大致意思是:在预编译阶段,代码并未运行,无法判断宏定义的值。最后查找到原因是我在上述步骤设置宏定义的时候,手误设置了TargetType==1,这本是一句需要执行才能得到结果的代码。所以无法在#if的条件编译中通过。
解决:在条件编译中不使用代码运行时才生成的量即可。
作者:风恣
原文链接:https://dreamcoffeezs.github.io/2018/02/10/iOS%E5%A4%9ATarget%E5%BC%80%E5%8F%91%E7%9B%B8%E4%BC%BCApp/