在开发过程中,您可能经常会遇到"duplicate symbol _xxx"的错误,大多都是变量重复,您可能需要给某一个类的变量改名字,为什么会出现类似的问题呢,我做了个试验,发现了很有意思的事情。
case1
A.h声明
extern NSString * kAppErrorDomain
A.m实现
NSString * kAppErrorDomain = @"这是在A文件声明的变量"
b.h声明
extern NSString * kAppErrorDomain
b.m实现
NSString * kAppErrorDomain ;//没有赋值
这时候你会发现,咦?我虽然在两个文件声明的同样的变量,但是并没有冲突,且可以正常运营,并且我可以很负责的告诉你,这两个kAppErrorDomain变量的地址都是同一个地址。
case2
b.m实现换一下
NSString * kAppErrorDomain = @"这是在B文件声明的变量"
运行报错,"duplicate symbol _kAppErrorDomain in:",我们想要的错误出来了。这就很正常了,你确实声明了相同的变量。
有同学说了,我之前定义过相同的变量,没问题啊。那ok,我们看一下没问题的相同变量是什么样的。
case1
a.h声明
extern NSString * const kAppErrorDomain;
a.m实现
NSString * const kAppErrorDomain = @"这是在A文件声明的变量"
b.h声明
extern NSString * const kAppErrorDomain;
b.m实现
NSString * const kAppErrorDomain = @"这是在B文件声明的变量"
运行成功,且使用没问题。为什么呢?我还没弄明白,但我可以只用一句代码让本可以运行成功的程序出错。
在a或b的.m增加
NSLog(@"%p",&kAppErrorDomain);
再编译试试,出错,"duplicate symbol _kAppErrorDomain in:",好玩么,就想看个地址,苹果不给看。那怎么解决这种问题?
case1
a.h声明修改
static NSString * const kAppErrorDomain;
a.m实现修改
static NSString * const kAppErrorDomain = @"这是在A文件声明的变量"
b.h声明修改
static NSString * const kAppErrorDomain;
b.m实现修改
static NSString * const kAppErrorDomain = @"这是在B文件声明的变量"
"这下大家满意了吧",也能打印值了,也能打印地址了,但你会发现,相同的变量具有不同的地址,因为static的作用域与他定义的位置相关,定义在文件就只在文件内有效,定义在方法内,就只在方法内有效。所以其实a与b各自存在一个kAppErrorDomain变量,其实他俩并不是公用一个。
case2
a.h,a.m不变,
把b.h修改为
#import "a.h"
b.m删除实现
运行程序,效果同样,相同的变量,不同的地址。这说明了#import一个有意思的地方,它其实是对import的文件做copy操作,这也就是为什么建议在.h文件尽量的少用#import,而是用@class。
ok,结束。