# 为什么这么做?

  现在有这么一个使用场景,基线能生成项目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 动态插入第三方代码的更多相关文章

  1. js动态插入标签代码(insertAdjacentHTML)

    做网页时通过ajax请求获取到数据后,有的需要把数据拼接到带有各种标签的字符串中,拼接完字符串就需要把字符串动态添加到网页上的某个位置,举个

  2. 动态插入的html代码,点击节点无效以及获取节点下标的方法

    动态插入的html,需要使用delegate或者on事件来监听,方式如下. 如果需要获取节点对应的下标,$(this).index()是无法获取的,需要以$(selectot).index(this) ...

  3. (转载)JAVA动态编译--字节代码的操纵

    在一般的Java应用开发过程中,开发人员使用Java的方式比较简单.打开惯用的IDE,编写Java源代码,再利用IDE提供的功能直接运行Java 程序就可以了.这种开发模式背后的过程是:开发人员编写的 ...

  4. XML 动态 插入 父类标示 子类标示

    由于第一次写博客,写的不好的地方,还请各位大神多多指点, 讲解一下:xml动态插入数据并保存,写这个时候费了我不少劲,最后终于皇天不负有心人让我搞出来了,特意分享给大家,写的不完美的地方还请大家多多指 ...

  5. JavaScript 动态插入 CSS

    写组件时有时想把一些组件特性相关的 CSS 样式封装在 JS 里,这样更内聚,改起来方便.JS 动态插入 CSS 两个步骤就可以 创建一个 style 对象 使用 stylesheet 的 inser ...

  6. FMDB处理动态插入语句

    昨天做一个需求,参数的数量不确定,所以无法使用这个API: - (BOOL)executeUpdate:(NSString*)sql, ... 但是用 - (BOOL)executeUpdate:(N ...

  7. jquery动态插入行

    这是一个利用jquery动态插入输入内容的代码. html代码: <div title="分表2" class="ui-edit" style=" ...

  8. jquery动态插入行,不用拼写html,简洁版

    这个一个利用jquery实现动态插入输入行效果小功能,不用在javascript里拼写html字符串,更简洁.高效. html代码: <div class="fitem"&g ...

  9. iOS_动态插入或删除行

    终于效果图: 分MVC三层设计;自己定义的Cell有两种;一种是MainCell,由ModelArr提供数据源;还有一种是插入的cell,由代码创建,而且由另外一个数组供状态数据 数据源部分: wat ...

随机推荐

  1. [论文阅读笔记] Community aware random walk for network embedding

    [论文阅读笔记] Community aware random walk for network embedding 本文结构 解决问题 主要贡献 算法原理 参考文献 (1) 解决问题 先前许多算法都 ...

  2. Scrum Master 生存指南

    近年来,出现了一批新兴且广受关注的岗位,以 Scrum Master 为典型代表.2018年,Scrum Master 的平均工资为98239美元.领英更是将其列为2019年最有前途的工作之一.但对于 ...

  3. Step By Step(Lua数据持久化)

    Step By Step(Lua数据持久化) 1. 数据文件:    我们可以利用Lua中table的构造式来定义一种文件格式,即文件中的数据是table构造并初始化的代码,这种方式对于Lua程序而言 ...

  4. Docker学习(12) Dockerfile构建过程

    Dockerfile的构建过程 以上为构建缓存

  5. Manjaro Linux安装singularity-container

    技术背景 容器化技术在各种生产领域已经得到了广泛的应用,这得益于容器的轻量化(相比于虚拟机而言),安全性(隔离弱于虚拟机,但是权限控制得当的情况下也可以认为是安全隔离的)以及系统级虚拟化带来的高可用性 ...

  6. CMOS图像传感器理解

    CMOS图像传感器理解 水流方向从左边流向右边,上面有一个开关,拧下去的时候水流停止,拧上去的时候水流打开.左边是水流的源头我们给它起个名字,叫做源端(就是源头的意思嘛),右边是水流出去的地方,也就是 ...

  7. Paddle概述

    Paddle概述 本文结合深度学习理论与实践,使用百度飞桨平台实现自然语言处理.计算机视觉及个性化推荐等领域的经典应用. 实践部分使用飞桨深度学习开源框架,适配最新的2.0版本,默认使用动态图编程范式 ...

  8. PyTorch 数据并行处理

    PyTorch 数据并行处理 可选择:数据并行处理(文末有完整代码下载) 本文将学习如何用 DataParallel 来使用多 GPU. 通过 PyTorch 使用多个 GPU 非常简单.可以将模型放 ...

  9. NVIDIA TensorRT:可编程推理加速器

    NVIDIA TensorRT:可编程推理加速器 一.概述 NVIDIA TensorRT是一个用于高性能深度学习推理的SDK.它包括一个深度学习推理优化器和运行时间,为深度学习推理应用程序提供低延迟 ...

  10. 图分析Rapids cuGraph

    图分析Rapids cuGraph 英伟达(Nvidia)建立的新的开源库可能是推进分析和使图形数据库更快的秘密要素. 在Nvidia GPU上进行并行处理. Nvidia很久以前就不再只是" ...