- 我们通过一个案例来理解全局符号的概念
- 创建一个
Framework 项目名称为HSOneFramework 、声明一个头文件HSOneFramework.h 、
#import <HSOneFramework/HSOneObject.h>
@interface HSOneObject : NSObject
- (void)testOneObject;
@end
@implementation HSOneObject
void global_object(){
NSLog(@"HSOneObject -- global_object");
}
- (void)testOneObject{
NSLog(@"HSOneObject -- testOneObject");
}
@end
- 再创建个
iOS--App Demo - 打开
HSGlobSymbol Demo 、将项目中文件都收缩后、点左下角点击添加 Files - 然后
Copy Items …、点击Options 、选中刚才创建的 HSOneFramework 的xcodeproj 项目—> Add - 发现会添加成这个样子
- 在当前
Xcode 操作环境下—> - 点击电脑左上角
File —> Save as Workspace —>- 编辑新的名称为
MultiProject.xcworkspace。 - 关闭当前项目。打开刚才创建的
MultiProject.xcworkspace 。两个合并的项目展现。打开后目录如下 - 下面我们在
HSGlobSymbol 的Target 处添加framework 。 - 选择
HSOneFramework.framework ,并且设置Embed 为Embed & Sign - 此时此刻、我们在
HSGlobSymbol 引入 刚才的framework 中头文件、会发现文件找不到的报错问题。 - 点开
HSOneFramework --> HSOneObject.h 文件、查看文件属性。 - 将文件访问控制权限改为 Public 即可。
- 多个项目合并为一个的时候、使用的
workspace 的作用是什么呢?
- 可重用性。多个模块可以在多个项目中使用。节约开发和维护时间。
- 节省测试时间。单独模块意味着每个模块都可以添加测试功能。
- 更好的理解模块化思想。
- 下面我们开始查看这个项目
- 在动态库的
HSOneObject.m 中我们实现了全局符号的函数、但是在.h中并没有进行声明。
void global_object(){
NSLog(@"HSOneObject -- global_object");
}
- 这个时候我们在
ViewController 中声明下这个全局符号。并且进行函数调用。
void global_object(void);
- (void)viewDidLoad {
[super viewDidLoad];
global_object();
}
- 此时编译正常通过、输出结果为我们在HSOneObject.m中的实现日志
HSOneObject -- global_object
- 由此可见、全局符号对我们整个项目是可见的、对使用的人是可见的。
- 此时此刻、我们对
global_object 进行 static 修饰。那就意味着它会变成本地符号,只能在定义的当前文件可用。 - 与此同时、我们在
ViewControler 再次对global_object 全局函数进行实现。那么会发生什么呢?
void global_object(void);
- (void)viewDidLoad {
[super viewDidLoad];
global_object();
HSOneObject *one = [[HSOneObject alloc]init];
[one testOneObject];
}
void global_object(){
NSLog(@"ViewController -- global_object");
}
- 运行正常、并且当前输出结果为控制器的日志。这是为什么呢?
- 在链接过程中、有一个二级命名空间的概念。
- 二级命名空间与一级命名空间
(two_levelnamespace & flat_namespace:) 。 - 链接器默认采用二级命名空间,也就是除了会记录符号名称,还会记录符号属于哪个
Mach-O ,比如会记录下来 _NSLog 来自Foundation 。 - 上述全局函数在调用时、有两个
Mach-O 文件记录了它的实现部分,HSOneFramework 和HSGlobSymbol 、根据二级命名空间原则,优先调用当前的Mach-O ,他们不会产生冲突。
|