在项目开发中,难免会遇到要同时维护多个app的情况,而如果这几个app有很大一部分的重复内容,其最好的解决方式,就是在同一个项目中设置不同的Target,这样既可以复用大部分的文件内容,又能针对不同的项目需求来进行个性化设置。以下就是基于这个需求来进行多个Target的设置。
1. 创建新的Target
创建新的Target有两种方式,一个是新建,一个是复制原有的Target;
为了区分两种方式的区别,项目初始为:
红框内为新添加的几个文件;
1.1. 新建Target
同新建项目一样,选择顶部菜单栏:File ->New -> Target...
在弹出的页面填写新的Target名称即可:
这样创建的Target会有单独的AppDelegate,而且会有单独的文件分类:
红框内为原有的文件,绿框内为新创建的Target文件;
这种方式创建的Target很多文件不能共用,但也有一些好处:独立的AppDelegate,不需要对新的Target进行配置,即可直接使用;
一般我们使用下面的方法进行复制一个Target,以达到共用文件的目的;
1.2 方式二:复制Target
选中需要复制的Target,然后右键选择 Duplicate,即可直接复制
复制之后的名称为:“愿名称 copy”;这里既是:“TargetTest copy”;另外在左侧文件列表会多出一个xxx-info.plist文件,即下图红框内文件:
这样创建的Target需要我们进行一些设置,重命名等!
修改Target名称
选中新的Target之后,再次单击,即可修改名称:
修改Bundle id
这时的Bundle Identifier和Display Name还是原先的Target名称,选中新的Target后,会显示新的Target配置文件,设置新的id和名称即可:
修改Scheme
此时的Scheme还是 TargetTest copy ,需要修改为和新的Target同名的:
在打开的页面中选中需要修改的Target后,再次点击即可进入编辑状态:
修改xxx-info.plist文件名称
默认生成的xxx-info.plist文件名称是TargetTest copy-Info.plist,当然,我们需要把它修改为和之前一致的,直接修改即可(建议保留如下格式):
修改之后,我们需要重新配置一下其路径,最简单的方式是,先将该文件删除引用,然后再添加进来:
然后在弹出页中选择 Remove Reference:
然后,再右键-> Add File to...,重新添加进来即可!
如果,我们需要区分的文件比较多,建议新建一个文件夹,然后将该plist文件移动到文件夹中:
接着Add File to...:
上面选中要添加的文件,最下面勾选要添加到的Target,其实这里只需要勾选First Target即可,因为我们要添加的文件就是到这个Target的,也可以勾选所有的Target;
配置info.plist文件路径
上面添加完info.plist文件后是这样的:
可以看到,右侧选中新的Target(FirstTarget)后, Identity 项是空着的。点击 Choose Info.plist File... 选择刚刚添加的Info.plist即可:
然后先选择一下其他的Target,再选择新添加的Target就会显示刚刚新加的Info.plist文件:
设置宏定义
由于设置了不同的Target,在我们编写代码的时候就需要知道哪个Target引用了哪个文件,在不同的Target中配置不同的参数等;这就需要设置用于区分对应Target的宏定义:Target -> Build Settings -> 搜索 macros
在 Preprocessor Macros 中可以分别设置 Debug模式和Release模式下的全局宏定义,一般是添加的一样的;在右边空白处双击可以弹出下面的视图:
点击左下角 + 可以新加宏定义
PS: 如果需要修改原有的宏定义,选中后,再次单击,即可进行编辑;如果需要删除,选中后,点击左下角的 - 即可删除;
设置完之后是这样的:
在使用的时候,我们既可以在代码中使用if判断,也可以在头文件中使用#if #endif判断:
例如,根据该宏引入不同的头文件,可以这样写:
#if FIRST_FLAG
#import "FirstUserModel.h"
#else
#import "UserModel.h"
#endif
在代码中可以这样使用:
if (FIRST_FLAG) {
NSLog(@"FirstTarget log");
} else {
NSLog(@"log");
}
如果有多个Target,既可以使用这个方式进行区分!
PS:如果需要在多个Target中使用同一个宏定义进行判断,可以在每个Target中都添加相应的宏,只不过修改其值即可,例如上面的如果想在原Target中使用FIRST_FLAG宏,可以在原Target中这样设置:
Swift项目设置标识符
在swift项目中没有宏定义的概念,也不能使用宏定义。Swift中对应OC中的宏定义有个flag(标识符)可供我们使用,在Build Setting中搜索:other swift flags
在右边空白处双击,即可弹出和OC一样的弹框,点击 + 添加即可!
PS:需要注意,这里添加标识的时候,需要在你自定义的标识符前加 “-D”;例如你的标识符为:MYFLAG,那么添加的时候要是:-DMYFLAG,而且不能像OC那样进行赋值。
设置完成后,即:
使用:
#if MYFLAG
print("自定义的Flag")
#endif
图片资源 Assets.xcassets
Assets的使用可以共用一个,也可以新建一个Assets,以供给不同的Target使用:
共用一个Assets
共用一个Assets的好处是,大部分的图标都可以进行复用,不需要额外拖入,这里主要是将如何设置不同的启动图和 App icon,如何不加载不需要的图标:
设置不同的App icon
点击右下方 + 选择新的icon或者launch image:
然后,加入相应的icon图标;
最后,将新的icon设置为新的Target的图标即可;
在TARGETS中选择你的Target -> General -> App Icons and Launch Images中 App Icons Source 引用到新建的那个icon即可:
设置不同的Launch Image
和设置不同的icon大致相同,新建一个Launch Image Asset,然后加入相应的启动图,最后再设置为新的Target的启动图即可!
只加载需要的图标
不同的项目使用的图标资源会有区别,如果复用了大部分的图标,而不想在编译的时候引入未使用的别的Target的图标,可以在相应的Target中的Build Phases下的 Copy Bundle Resources 中删除不需要图标的引用即可!
PS:同样,Build Phases下的Comolle Sources中也可以删除不需要的.m文件的引用!
新建不同的Assets
同新建文件一样,右键 -> New File...
在Resource中选择 Asset Catalog,Next,起一个文件名,选择相应的Target:
拖入药添加的图片,配置相应的icon和启动图即可!
PCH文件
如果原Target有PCH文件,复制新的Target的时候,默认是一起复制了的,如果需要添加新的PCH文件,可以新建之后,在 Building Setting中搜索:“prefix header”,将路径添加进去即可!
Podfile文件配置
如果项目中使用了Pod进行第三方库的项目管理,需要针对新的Target进行一些第三方库的支持,否则,在不同的Target进行编译工程的时候,可能会报找不到头文件的错误;只需要在原Podfile文件中添加一个“Target - do - end ” 即可:
例如,原Podfile文件如下:
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
target 'TargetTest' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
# Pods for TargetTest
pod 'AFNetworking', '~> 3.1.0'
pod 'Masonry', '~> 1.1.0'
pod 'MBProgressHUD', '~> 1.1.0'
target 'TargetTestTests' do
inherit! :search_paths
# Pods for testing
end
target 'TargetTestUITests' do
inherit! :search_paths
# Pods for testing
end
end
修改之后的如下:
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
target 'TargetTest' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
# Pods for TargetTest
pod 'AFNetworking', '~> 3.1.0'
pod 'Masonry', '~> 1.1.0'
pod 'MBProgressHUD', '~> 1.1.0'
target 'FirstTarget' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
# Pods for FirstTarget
pod 'AFNetworking', '~> 3.1.0'
pod 'Masonry', '~> 1.1.0'
pod 'MBProgressHUD', '~> 1.1.0'
end
target 'TargetTestTests' do
inherit! :search_paths
# Pods for testing
end
target 'TargetTestUITests' do
inherit! :search_paths
# Pods for testing
end
end