- 我们通过一个案例来理解全局符号的概念
- 创建一个
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,他们不会产生冲突。
|