使用xcodeproj 动态插入第三方代码
# 为什么这么做?
现在有这么一个使用场景,基线能生成项目A,项目B,项目C...如果只有项目A中使用SDK_A,其他项目都不使用,这时候就需要对基线进行差分,只有当我切换到项目A时,才插入SDK_A。
不同于cocoapods的库管理方式,xcodeproj是通过脚本在编译前向项目中插入指定代码文件。
# Xcode中的项目结构

项目中都会有个主target作为根节点,底下有很多group节点,这些group节点管理者三类文件
1. 常规的 .h/.m 文件
2. 资源文件
3. 库文件,分为静态库.a文件、动态库.framework文件、阉割版的动态库embed franework文件
## 如何引入
这里涉及到xcodeproj的具体使用,贴一下官方文档:
#获取项目
$project = Xcodeproj::Project.open($project_path); #获取target,通常取第一个为项目的主target
$target = $project.targets.first # 获取插件目录的group,如果不存在则创建
$group_One = $project[$plugin_folder] || $project.main_group.find_subpath(File.join($plugin_folder), true); # 在目标目录新建group目录
$group = $group_One.find_subpath($folderName, true)
$SDK_PATH = $group_One.real_path.to_s + "/" + $plugin_folder + "/" + $folderName # 判断SDK_PATH目录下是否存在第三方代码,不存在则退出
if !FileTest::exists?($SDK_PATH)
puts "SDK file not found in #{$SDK_PATH}"
exit 1
end
* project_path 是项目的路径
* plugin_folder 是插入的目录名称,它是创建在项目目录底下的
* folder_name 是插入的第三方库的文件夹的名称,它是创建在plugin_folder目录底下的
注意,这里的第三库的代码文件其实和项目的代码是放在一块的,我们要做的只是将它和项目关联起来,也就是在XXX.xcodeproj文件中添加其引用。具体的关联就是建立target底下的group组后 添加上述3类文件的引用。
1. .h/.m 文件添加引用
if filePath.to_s.end_with?(".h") then
fileReference = aGroup.new_reference(filePath);
# aTarget.source_build_phase.add_file_reference(fileReference, true)
elsif filePath.to_s.end_with?(".m", ".mm", ".cpp") then
fileReference = aGroup.new_reference(filePath);
aTarget.source_build_phase.add_file_reference(fileReference, true)
需要注意的是.h文件只需要 在group底下new一个reference,.m文件需要将group底下的reference添加进source_build_phase
2. 资源文件添加引用
if filePath.to_s.end_with?(".bundle",".plist" ,".xml",".png",".xib",".js",".html",".css",".strings")
fileReference = aGroup.new_reference(filePath);
aTarget.resources_build_phase.add_file_reference(fileReference, true)
根据资源文件创建其group的reference后,需要将其添加进resources_build_phase
3. 库文件的引用
if filePath.to_s.end_with?(".framework" ,".a")
fileReference = aGroup.new_reference(filePath);
build_phase = aTarget.frameworks_build_phase;
build_phase.add_file_reference(fileReference);
if $isEmbed == true
#添加动态库
$embed_framework.add_file_reference(fileReference)
#勾上code sign on copy选项(默认是没勾上的)
$embed_framework.files.each do |file|
# puts "entry filePath : #{filePath} fileRef path : #{file.file_ref.path}"
if filePath.end_with?(file.file_ref.path) then
if file.settings.nil? then
# puts "setting is nil"
file.settings = Hash.new
end
file.settings["ATTRIBUTES"] = ["CodeSignOnCopy", "RemoveHeadersOnCopy"]
end
end
end
库文件需将 reference 添加进frameworks_build_phase,如果是embed framework还需将其添加进embed_frameworks_build_phase,其在xcodeproj中的具体类型是PBXCopyFilesBuildPhase
## 如何清除
因为SDK_A仅仅是项目A使用,如果从项目A切换到项目B,此时就得从XXX.xcodeproj文件中清除关于SDK_A的所有引用,其实是添加引用的一个逆向工程。
上文中我们说到 将SDK_A插入{$PROJECT_PATH}/plugin_folder,所以只需遍历这个group,清除其中所有的reference即可。
def removeBuildPhaseFilesRecursively(aTarget, aGroup)
aGroup.files.each do |file|
if file.real_path.to_s.end_with?(".m", ".mm", ".cpp") then
aTarget.source_build_phase.remove_file_reference(file)
elsif file.real_path.to_s.end_with?(".bundle",".plist" ,".xml",".png",".xib",".js",".html",".css",".strings") then
aTarget.resources_build_phase.remove_file_reference(file)
elsif file.real_path.to_s.end_with?(".framework" ,".a")
aTarget.frameworks_build_phase.remove_file_reference(file)
# remove embed ref
if $isEmbed && !$embed_framework.nil?
$embed_framework.remove_file_reference(file)
end
end # extra r+emove file ref
file.remove_from_project
end aGroup.groups.each do |group|
# puts "group path : #{group.path}"
if group.path == "embed"
$isEmbed = true
end
removeBuildPhaseFilesRecursively(aTarget, group)
$isEmbed = false
end
end
* .m 文件的引用由source_build_phase移除
* 资源文件的引用由resources_build_phase移除
* 库文件的引用由frameworks_build_phase移除,其中embed的framework还需由embed_framework_build_phase额外移除一下
# 后记
xcodeproj 其实不光只是添加引用,xcode中的build_settings的所有选项几乎都可以通过xcodeproj的脚本控制,这里先按下不表。
最后附一下 github的传送门地址:https://github.com/xuanyuelin/ManuallyInsertCodes
使用xcodeproj 动态插入第三方代码的更多相关文章
- js动态插入标签代码(insertAdjacentHTML)
做网页时通过ajax请求获取到数据后,有的需要把数据拼接到带有各种标签的字符串中,拼接完字符串就需要把字符串动态添加到网页上的某个位置,举个
- 动态插入的html代码,点击节点无效以及获取节点下标的方法
动态插入的html,需要使用delegate或者on事件来监听,方式如下. 如果需要获取节点对应的下标,$(this).index()是无法获取的,需要以$(selectot).index(this) ...
- (转载)JAVA动态编译--字节代码的操纵
在一般的Java应用开发过程中,开发人员使用Java的方式比较简单.打开惯用的IDE,编写Java源代码,再利用IDE提供的功能直接运行Java 程序就可以了.这种开发模式背后的过程是:开发人员编写的 ...
- XML 动态 插入 父类标示 子类标示
由于第一次写博客,写的不好的地方,还请各位大神多多指点, 讲解一下:xml动态插入数据并保存,写这个时候费了我不少劲,最后终于皇天不负有心人让我搞出来了,特意分享给大家,写的不完美的地方还请大家多多指 ...
- JavaScript 动态插入 CSS
写组件时有时想把一些组件特性相关的 CSS 样式封装在 JS 里,这样更内聚,改起来方便.JS 动态插入 CSS 两个步骤就可以 创建一个 style 对象 使用 stylesheet 的 inser ...
- FMDB处理动态插入语句
昨天做一个需求,参数的数量不确定,所以无法使用这个API: - (BOOL)executeUpdate:(NSString*)sql, ... 但是用 - (BOOL)executeUpdate:(N ...
- jquery动态插入行
这是一个利用jquery动态插入输入内容的代码. html代码: <div title="分表2" class="ui-edit" style=" ...
- jquery动态插入行,不用拼写html,简洁版
这个一个利用jquery实现动态插入输入行效果小功能,不用在javascript里拼写html字符串,更简洁.高效. html代码: <div class="fitem"&g ...
- iOS_动态插入或删除行
终于效果图: 分MVC三层设计;自己定义的Cell有两种;一种是MainCell,由ModelArr提供数据源;还有一种是插入的cell,由代码创建,而且由另外一个数组供状态数据 数据源部分: wat ...
随机推荐
- 大数据学习之路——MySQL基础(一)——MySQL的基础知识与常见操作
一.存储引擎 1.含义 存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建.查询.更新和删除数据.不同的存储引擎提供不同的存储机制.索引技巧.锁定水平等功能,使用不同的存储引 ...
- Redis学习笔记八:集群模式
作者:Grey 原文地址:Redis学习笔记八:集群模式 前面提到的Redis学习笔记七:主从复制和哨兵只能解决Redis的单点压力大和单点故障问题,接下来要讲的Redis Cluster模式,主要是 ...
- Jmeter(四十九) - 从入门到精通高级篇 - jmeter使用监视器结果监控tomcat性能(详解教程)
1.简介 上一篇宏哥讲解了利用jmeter的插件来监控服务器资源,这一篇讲解分享如何使用jmeter的监视器结果监控tomcat性能. 2.准备工作 文章标题中提到jmeter和tomcat,那么只需 ...
- Django(44)drf序列化源码分析(1)
序列化与反序列化 一般后端数据返回给前端的数据格式都是json格式,简单易懂,但是我们使用的语言本身并不是json格式,像我们使用的Python如果直接返回给前端,前端用的javascript语言 ...
- 同一个Controller里的同一个Service实例,在当前的Controller里的不同方法中状态不一致
直接上代码如下: @Controller@RequestMapping("/views/information")public class PubContentController ...
- vmware workstation linux虚拟机点击suspend会卡死
vmware workstation linux虚拟机点击suspend会卡死, 现象如图, 我测过很多发行版都有这个问题 临时解决方案是关闭suspend功能 sudo systemctl mask ...
- cuDNN概述
cuDNN概述 NVIDIACUDA深度神经网络库(cuDNN)是GPU加速的用于深度神经网络的原语库.cuDNN为标准例程提供了高度优化的实现,例如向前和向后卷积,池化,规范化和激活层. 全球的深度 ...
- MLPerf Inference 0.7应用
MLPerf Inference 0.7应用 三个趋势继续推动着人工智能推理市场的训练和推理:不断增长的数据集,日益复杂和多样化的网络,以及实时人工智能服务. MLPerf 推断 0 . 7 是行业标 ...
- 新版 ZooKeeper 启动时一直报: Starting zookeeper … FAILED TO START
https://www.pianshen.com/article/74551582443/ 这里引用别人博客,自己验证过,确实如此
- 使用IDEA创建Maven项目
一.创建一个普通的Maven项目 1.启动IDEA 2.创建一个Maven项目 3.Maven的目录结构 二.使用模板创建一个MavenWeb项目 1.启动IDEA 2.创建一个MavenWeb项目 ...