前言
最近对项目进行优化,就顺便写一些日常开发中会用到的中高级开发技巧。这篇文章聊一下下面三个内容:多环境配置,Mach-O与链接器,Symbol
。
多环境配置
聊到多环境配置,我们先说几个概念上图就是每个项目都存在的,下面解释下红框内的内容:
- 1.
Project:包含了项目所有的代码,资源文件,所有信息。
- 2.
Target:对指定代码和资源文件的具体构建方式。
- 3.
Scheme:对指定Target的环境配置。
我尝试加入各种iOS开发交流群,群里的气氛大致就是:学什么iOS,iOS完了,OC完了,群里大致三种人:谁有企业开发证书,马甲包了解一下,至今,大部分iOS开发群还都是仅供吹水用,偶尔能碰见几个好心人解决一下问题,作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS开发交流群:130 595 548,不管你是小白还是大牛都欢迎入驻 ,让我们一起进步,共同发展!(群内会免费提供一些群主收藏的免费学习书籍资料以及整理好的几百道面试题和答案文档!)
我们创建好项目,项目默认两个环境Debug和Release环境
,在开发过程中我们也会有两套或者多套服务器环境
,每个环境的地址不同
,粗糙的写法就是如下图所示:
它只能满足两种环境
,无法
适应多环境
,下面我们介绍几种多环境配置方法
Targets进行多环境配置
- 1.我们可以在Targets中创建多个Target
此时我们只是复制了一个Target,没有产生新的代码,就是复制了一套配置,运行也不会报错
- 2.我们修改一下Bundle Id
- 3.修改Info.plist文件
这些修改后,就会发现有两个项目可以选择
,分别运行后,就会发现有两个App
通过这个我们可以配置不同
的icon进行区别
- 4.设置宏
我们可以根据项目设置
自己相应的宏
总结
这种多环境配置有一下缺点:
- 1.会存在
多个info.plist文件
- 2.环境多了,
配置就会比较乱
下面我们再介绍比这个更好的方式
Configurations多环境配置
我们知道在Scheme中我们是可以选择环境添加完成后再看看Scheme就会发现多了个刚加入的Test它和上面得Scheme是一一对应的
【问题】:我们每次运行项目都要在上图的Scheme进行切换环境,很不方便,那么有什么办法解决这个问题
- 1.创建Scheme,如下图位置
- 2.点击左下角+进行创建,创自己想要的环境名称
- 3.关闭页面后,再来看项目,就会发现有刚创建好的环境了
- 4.对创建的Scheme和Configurations关联
-
5.跟服务器环境进行绑定
- 1.在项目Build Settings里新建User-Defined,起名就叫HOST_URL
- 2.在HOST_URL不同的环境配置不同URL
- 3.在Info.plist进行配置,将近暴露出来
- 4.在项目中应用
5.验证
- 1.在项目Build Settings里新建User-Defined,起名就叫HOST_URL
总结
此时我们就解决了上面你那个问题,但是这种方式还是不够完美,因为项目中要使用cocoapods对第三方管理
,此时用上面的方法对Build Settings设置就比较的繁琐
,那么有没有一种方法对Build Settings进行集中管理呢?下面我们介绍另一种方式
.xcconfig多环境配置
初始.xcconfig
在使用cocoapods对第三方进行管理
,其实就是通过.xcconfig文件进行管理
的,创建好cocoapods会自动
根据环境帮我们生成好.xcconfig文件
.xcconfig文件内容是已
Key-Value
形式存在,'='左侧是key值
,右侧为value值
在项目里会对不同的环境
和不同的.xcconfig进行绑定
配置自己的.xcconfig文件
- 1.创建Config文件,在文件中创建.xcconfig文件
注意命名规则:.xcconfig文件所在的文件夹名称+项目名称+.环境名称
- 2.根据项目环境配置自己创建的.xcconfig文件
使用.xcconfig
我们还想对不同的环境设置不同的请求地址,那么可以再.xcconfig进行设置
-
1.创建并设置.xcconfig内容
- 2.设置plist文件
- 3.项目中使用
- 4.验证
总结
这种设置方式要比上面的简化了不少,但是.xcconfig文件的功能不只有这些,下面我们扩展一下
.xcconfig扩展
上面我们介绍了简单的配置URL
,.xcconfig文件
是可以配置Build Settings
里面的内容
,比如我们平时配置动态库,静态库
时,要配置到Other Link Flags
,通过.xcconfig
我们可以直接配置
,例如:我们配置AFN
- 1.在.xcconfig中写如下代码
- 2.build一下,再去查看
Other Link Flags
,发现写的已经配置进去了
通过上面的操作我们可以知道,Build Settings
的所有配置
都是可以通过.xcconfig
文件进行管理
的。我们来解释下.xcconfig的内容:OTHER_LDFLAGS是Build Settings里面的一个缩写
,其它设置缩写是什么呢?
推荐个地址:Xcode Build Settings
左侧是对应的Build Settings的Key名称,右边则是其对应的缩写
比如我们想配置Header Search Paths
,那么在网页上搜索:Header Search Paths,它对应的缩写:HEADER_SEARCH_PATHS
.xcconfig冲突
问题一
我们项目都会通过cocoapods管理第三方
,最开始介绍.xcconfig的时候,说了pods
会自动帮我们生成.xcconfig文件
,那此时项目中就会有4个.xccongig文件
我们发现一个环境
只能配置一个.xcconfig文件
,那该怎么办才能让自己写的和pods生成的都能生效
呢?
- 先给我们的TestOC添加Podfile,进行更新
发现报警告,警告的意思是设置好了CocoaPods但是项目中你
已经设置了其它的.xcconfig文件
,导致了Pods设置的.xcconfig文件不会生效
,我们要解决这个冲突
- 有一个关键
include
它可以引入其他的文件,让引入的文件生效
上面的报错显示了Pods生成的.xcconfig路径:"Target Support Files/Pods-TestOC/Pods-TestOC.debug.xcconfig
",我们引入到自己的.xcconfig文件中
- 运行项目,发现报错
报错说是
找不到Pods生成的.xcconfig
,我们查看Pods生成的.xcconfig文件,发现它的根目录是Pods
- 在看Pods会不会报警告
发现Debug模式下不会再报警告,但是Release还会报警告,原因是我们release下的.xcconfig没有配置
问题二
我们看到Pods生成的.xcconfig
里也会有OTHER_LDFLAGS
,我们自己写的.xcconfig
中也存在OTHER_LDFLAGS
,我们再去看下项目的Other Link Flags
,发现Pods
生成的.xcconfig没有生效
,那么怎么才能让我们写的和Pods生成的都生效呢?
- 使用
inherited
进行继承
- 运行项目
- 验证
总结
我们通过.xcconfig
对项目进行配置
,我们可以通过.xcconfig+Scheme
方式进行统一管理,这样既省时,又省事
Mach-O与链接器
Mach-O初识
【Mach-O定义】:Mach-O(Mach Object)
是macOS、iOS、iPadOS存储程序和库
的文件格式
。对应系统通过应用二进制接口
(application binary interface,缩写为ABI
)来运行该格式的文件
。
Mach-O格式
用来替代BSD系统
的a.out格式
。Mach-O文件
格式保存
了在编译过程和链接过程
中产生
的机器代码和数据
,从而为静态链接
和动态链接
的代码提供
了单一文件格式
。
查找项目的Mach-O文件
当我们运行项目是,项目会生成一个.app文件我们可执行文件的调用过程大致如下:
- 1.调用
fork
函数,创建一个process
- 2.调用
execve
或其衍生函数,在该进程上加载,执行我们的Mach-O
文件 当我们调用时execve
(程序加载器),内核实际上在执行以下操作:- 1.将文件加载到内存
- 2.开始分析
Mach-O
中的mach_header
,以确认它是有效的Mach-O
文件
分析Mach-O文件
查看可执行文件有两种方式:
- 1.通过
MachOView
,也就是我们所说的烂苹果 - 2.通过命令:
objdump --macho --private-headers
下面我们通过命令行的方式查看可执行文件,其实macho = 文件配置 + 二进制代码
查看Mach-O文件,可以解释项目中的不少问题,我们举几个问题:
- 项目的入口为什么为main函数
红框内的就是
指定入口
,同样我们可以通过更换指定入口,来达到更换入口的目的
我们还可以通过Mach-O
可以看到一些加载系统依赖的库
我们发现这个文件展示的内容很多用不到
,需要简化一下,上面说了Mach-O是一个可读写文件
,所以可以写一个读取Mach-O的文件
,来移除这些不必要的东西
(怎么写后面文章在说)
发现少了很多东西,通过这个再次证明Mach-O是可读可写的
链接器
链接的本质
在项目中在编译过程中会生成.o文件(也就是目标文件),如下图所示:目标文件就是将我们写的代码放到
相应的位置
,比如我们写的全局变量,代码,全局符号
,在编译的过程中会根据不同的特性
进行分类
。
一个项目中会有多个.o文件
,而连接的本质就是把多个目标文件组合成一个文件
。
查看符号
一个项目有很多.m和.h文件
,在编译过程中会生成很多的.o文件
,那么在合并的过程中我们可以更改暴露给外界的信息
吗?
回答这个问题前,我们需要先看到符号表,下面先介绍几个概念:
- 1.
Symbol Table:就是用来保存符号。
- 2.
String Table:就是用来保存符号的名称。
- 3.
Indirect Symbol Table:间接符号表。保存使用的外部符号。更准确一点就是使用的外部动态库的符号。是Symbol Table的子集。
创建调试Demo
我们先弄个项目,让需要打印的符号信息
直接展示在终端
,方便我们后面调试
。这首先会牵扯到私钥和重定向
- 我们现在
Build Phases
创建Run Script
这个会在运行过程打印信息
- 新建终端
红框为
终端标识
,输入tty
,会打印一个像链接
一样的东西,这个就是这个终端的位置
- 然后我们将上面的信息copy到
Run Script
的打印上,对打印地址进行重定向
代码的意思就是讲
打印信息重定向到终端
- 编译代码
可以看到终端打印了我们刚才输入的信息
问题一:怎么让Xcode直行我们需要的代码
- 这就需要用到我们前面讲的
.xcconfig文件
,还据上面的例子,以Url为例
- 改动
Run Script
指令
- 编译代码
我们在.xcconfig上配置的地址就给打印出来了
通过脚本打印
- 这边写好了一个脚本(后面有文章来讲如何写脚本),把重要部分贴出来
这个脚本需要三个参数,分别为:
CMD,CMD_FLAG,TTY
,我们需要在.xcconfig
中对这个三个参数进行赋值
- 在.xcconfig中赋值
CMD_FLAG中的-pa的意思:
-p是不排序的意思
,-a是显示所有符号
,包含调试符号
- 更改
Run Script
指令,让其执行我们写的脚本
SRCROOT:代表当前代码路径
- 都配置好后,进行编译
发现打印出来了
- 优化,.xcconfig内容改写一下
再次运行还是会成功
写到最后
文章讲的比较细,写的也比较累,后面可能不会写这么细了!文章中间会牵扯到脚本,后面会写文章聊一下脚本语法。这部分文章实际开发中会有所使用,文章没写完,下篇文章会接着这部分继续讲下去。希望大家能够多多交流,共同进步