欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS【Undefined symbols for architecture i386: 错误的解决办法】

程序员文章站 2022-05-16 10:21:22
ios【undefined symbols for architecture i386: 错误的解决办法】 因为我是在真机上编译的项目,所以报错的架构(cpu指令集)为arm64。 如果我们使用64...

ios【undefined symbols for architecture i386: 错误的解决办法】

因为我是在真机上编译的项目,所以报错的架构(cpu指令集)为arm64。

如果我们使用64位模拟器(iphone simulators 5s 或更高版本)编译或者运行项目,就会报以下错误:
undefined symbols for architecture x86_64:
如果我们使用32位模拟器(iphone simulators 5 或更低版本)编译或者运行项目,就会报以下错误:
undefined symbols for architecture i386:

undefined symbols for architecture xxx:类似的错误是一个开发中经常遇到的问题,凡是涉及到第三方静态库的项目,都不可避免的遇到过这一类错误。为了说明错误的原因和加深对解决方案的理解。笔者采用了故意复现问题的方式来验证问题的解决方案:

即:故意给工程进行错误的配置或者删除某些配置,使工程编译不通过,然后记下编译器报的错误,验证什么情况下会报这种错。

首先声明,我的工程中引用(并非通过cocoapods引用)了友盟的统计sdk,名称叫做libmobclicklibrary.a。存储在工程的third_party目录下,如下图:

iOS【Undefined symbols for architecture i386: 错误的解决办法】

静态库目录

原因之一:没有链接lib库而报错

lib是library的意思,lib库就是指后缀名为.a的静态库。

(1) 删除general -> linked frameworks and libraries 下的libmobclicklibrary.a。如下图分别是删除前和删除后的对比:

删除前:iOS【Undefined symbols for architecture i386: 错误的解决办法】

此时链接了静态库

删除后:iOS【Undefined symbols for architecture i386: 错误的解决办法】

此时不再链接静态库

(2) 再次真机编译项目,我们就能如愿以偿的看到两个经典的的错误 "objc_class$_mobclick", referenced from: 和 linker command failed with exit code 1 (use -v to see invocation),点击第一个错误,如下图:

iOS【Undefined symbols for architecture i386: 错误的解决办法】

snip20161219_11.png

(3)然后看到 undefined symbols for architecture arm64:

iOS【Undefined symbols for architecture i386: 错误的解决办法】snip20161219_4.png

但是我们怎么知道是没有链接libmobclicklibrary.a库而不是其他的什么库呢?这还要取决于这句"_objc_class_$_mobclick", referenced from:。其中_objc_class_$_mobclick中的mobclick就是我们引用的libmobclicklibrary.a中的一个文件。因为我真的是在aliyunsalescustomerlisttableviewmanager.m中通过#import "mobclick.h"引用了mobclick.h,如下图:

iOS【Undefined symbols for architecture i386: 错误的解决办法】snip20161219_12.png

当然,如果我们引用了libmobclicklibrary.a库中的其他文件,那么objc_class$_后面就不是mobclick了,这个大家应该是很好理解的。

有的时候,因为后面的类名跟第三方的库名没有任何相似处,比如库名叫做libaaa.a,而报错的类名却是bbb。此时,我们通过后面的类名根本不能准确的判断出这个bbb属于哪个库,也就不知道该链接哪个库。这种情况下,我们可以通过referenced from:提示后面的文件名来判断bbb到底属于哪个静态库,因为我们自己的某个类文件不太可能import很多第三方的库,这种情况下,采取这种方式比较好判断。

总结:综上,我们可知:项目中如果用到了某个第三方静态库,但lib静态库或者framework静态库没有被链接时,就会遇到undefined symbols for architecture xxx这一类的错误。

原因:编译项目时,因为静态库没有链接进工程,所以静态库就不会参与编译,而项目某些文件(.m文件)又引用(或者说依赖)了静态库,所以自然会报错,而报的错就是经典的 undefined symbols for architecture xxx这一类的错误。

解决方案:下次遇到这类问题,我们只需要在linked frameworks and libraries 中添加指定的静态库即可!


还原项目

因为刚才删除了libmobclicklibrary.a文件,我们要想让项目可以恢复到完美编译运行的状态,需要在linked frameworks and libraries 添加libmobclicklibrary.a库,如下图:

因为是第三方库,不是提供的库,所以需要到我们自己的目录中添加:如下图展示了添加步骤:

iOS【Undefined symbols for architecture i386: 错误的解决办法】

第一步:点击添加

iOS【Undefined symbols for architecture i386: 错误的解决办法】

第二步:点击add other

iOS【Undefined symbols for architecture i386: 错误的解决办法】

第三步:选中静态库点击open

至此,缺失的静态库已经被链接进工程中,再次编译项目就不会报这个错误。当然,如果还报类似错误,说明你的项目中还需要链接其他的静态库,链接方法相同。

原因之二:没有链接.framework静态库而报错

上面说明了工程中因为缺少链接lib库导致报错的一种情况。ios开发中有两种格式的静态库(.a格式和.framework格式)。所以,我们也不难猜测:缺少链接.framework格式的静态库也会导致同样的错误。

如果我们引用的第三方库并不是.a格式的静态库,而是.framework格式的静态库,在linked frameworks and libraries中没有被链接的情况下,也会报同样的错误。比如我在linked frameworks and libraries 中删除 pushcentersdk.framework静态库(这个静态库存在于木纹中,不是cocoapods管理的),如下图:

(1)在linked frameworks and libraries中删除pushcentersdk.framework

 

iOS【Undefined symbols for architecture i386: 错误的解决办法】

删除.framework静态库

(2)模拟器编译项目,出现以下三个错误:

iOS【Undefined symbols for architecture i386: 错误的解决办法】

因为缺少链接的静态库所以编译出现错误

(3)点击第一个错误,查看错误详情,如下图:

iOS【Undefined symbols for architecture i386: 错误的解决办法】

错误详情

发现:如果缺少链接.framework格式的静态库,也会报相同的错误,所以,不管我们缺少链接的是.a静态库还是.framework静态库,只要在link frameworks and libraries 中没有正确链接进去,都会报相同的错误,即:undefined symbols for architecture xxx:。

值得注意的是,此处报了三个错误,原因在于,yunfupushcenter.m文件中引用了pushcentersdk.framework的两个文件(如下图),所以会多报一个错误,这个是比较好理解的:

iOS【Undefined symbols for architecture i386: 错误的解决办法】

引用了framework中的两个文件

原因之三:extern引用不存在的全局变量而报错

开发中,我们很有可能用到全局变量,比如在delegate.m文件中定义了一个int 型全局变量globalvar,在viewcontroller.m文件中通过extern int globalvar; 而引用a.m文件的这个全局变量。这样是没问题。但是如果我们不小心把extern int globalvar 写成extern int globalvariate,且在viewcontroller.m文件中使用了这个globalvariate变量(代码如下)。

#import "appdelegate.h"

@interface appdelegate ()

@end

@implementation appdelegate

int globalvar; // 生命一个全局变量
- (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions {
return yes;
}
#import "viewcontroller.h"

@interface viewcontroller ()

@end

@implementation viewcontroller

extern int globalvariate; // 引用一个不存在的全局变量
- (void)viewdidload {
[super viewdidload];

globalvariate = 10; // 给不存在的全局变量赋值
}

@end

编译上面代码也会报同样的错误,如下图:

iOS【Undefined symbols for architecture i386: 错误的解决办法】

点击错误查看详情,如下图:

iOS【Undefined symbols for architecture i386: 错误的解决办法】

原因:因为extern int globalvariate并没有定义名为globalvariate的变量,而是引用了一个名字叫做globalvariate的全局变量。当我们使用globalvariate时候,系统发现这个变量根本没有定义,就会报这个错误。