iOS集成第三方常见坑

最近这段时间,一直在研究webrtc,写iOS的时间很少,但是项目催得急,所以今天做了点iOS的工作。集成SDK本应该是很简单的一件事情,但当集成到一个维护长达五年的项目中,问题就多得一批。这里就顺便把常见的坑总结下。

小坑

笔者这里的小坑大都是指不需要我们改很多东西的情况,比如价格flag,或者设置一下search path之类的。

NSAppTransportSecurity

如果需要集成的SDK做得并不是那么好,很有可能在请求http的时候不成功。这个时候需要在plists文件设置一下,暂时退回到http协议。

  1. 在项目的info.plist中添加一个Key:NSAppTransportSecurity,类型为字典类型。
  2. 然后给它添加一个Key:NSAllowsArbitraryLoads,类型为Boolean类型,值为YES

pod 本地仓库太旧了或者pod search 搜索不到相关库

比如在执行pod install的时候出现找不到,比如什么头文件找不到之类的。解决办法就是升级下pod库

unrecognized selector sent to instance

很多时候这个问题是因为分类的问题。解决办法:
工程--->Building Setting ——》Linking———>other linker flags 添加 -ObjC 或者-all_load

文件件.h找不到

直接在Building Setting里面设置搜索路径。比如在有同学在集成支付宝的时候就经常遇到:



解决办法:


大坑

这里的大坑就是并不那么简单的就可以解决的,至少需要你去了解下一些基本原理才能搞定的。

Undefined symbols for architecture xxx

这个问题大部分情况下还是比较好解决的,解决思路大致分为如下几个:

  1. 大部分情况下是忘记添加了某个系统framework或dylib,比如你在项目中使用了sqlite3,但是没有添加libsqlite3.dylib,就会出现这个问题。解决办法是增加对应的framework或dylib。
  2. 如果是在C++里调用C函数,检查是否有添加extern "C",这可以通过观察错误提示中的函数名形式来决定,如果是C函数而以C ++的方式调用就需要添加extern "C"。
  3. 如果是把其它工程的xcodeproj文件加入到当前项目中,检查Build Phases中的Target Dependencies有没有添加依赖,以及General中的Linked Frameworks and Libraries有没有添加相关的.a文件。
  4. 如果添加.a文件编译无错而添加xcodeproj文件编译出错可参考3
  5. 如果添加.a文件编译出错,首先检查其对应的头文件是否添加正确,或者在Build Setting中有没有添加对应的Header Search Path路径;其次检查.a文件的c++编译选项与当前项目的c++编译选项是否一致;最后检查.a文件与当前项目的CPU架构信息是否一致
  6. 如果是使用了静态库,真机Debug测试时正常,而在执行for iOS Device测试时报这个错误,很可能是因为静态库支持的架构不全。出现这种情况是Build Setting中的Build Active Architecture Only在Debug下设为Yes,从而使得真机Debug测试正常。

符号文件冲突🎯

特征就是出现duplicate symbol这种标志。解决方法由易到难有如下几个:

  1. 对项目buildsetting里的other linker flags进行修改。详细的方法可以看看这里iOS 解决一个因三方静态库冲突产生的duplicate symbol的问题
  2. 这个方法就是从.a中把冲突的.o删去。详细步骤如下。
  • 查看库所包含的CPU架构
    打开终端输入如下命令:
cd /Users/fww/Desktop/temp 
lipo -info temp.a 

输出结果:

Architectures in the fat file: temp.a are: i386 x86_64 armv7 arm64
  • 分离不同架构的静态库
    也就是说这里将会从xxx.a中分离出i386 、x86_64、 armv7 、arm64 四个架构下的静态库,分别取名temp_i386.a,temp_x86_64.a,temp_armv7.a,temp_arm64.a: 在终端中继续输入如下命令:
lipo -extract_family i386 -output temp_i386.a temp.a lipo -extract_family x86_64 -output temp_x86_64.a temp.a lipo -extract_family armv7 -output temp_armv7.a temp.a lipo -extract_family arm64 -output temp_arm64.a temp.a

验证:

lipo -info temp_i386.a input file temp_i386.a is not a fat file Non-fat file: temp_i386.a is architecture: i386
lipo -info temp_x86_64.a input file temp_x86_64.a is not a fat file Non-fat file:temp_x86_64.a is architecture: x86_64
lipo -info temp_armv7.a input file temp_armv7.a is not a fat file Non-fat file: temp_armv7.a is architecture: armv7
  • 删除冲突的xxx.o
ar -d temp_i386.a GDataXMLNode.o ar -d temp_x86_64.a GDataXMLNode.o ar -d temp_armv7.a GDataXMLNode.o ar -d temp_arm64.a GDataXMLNode.o 
  • 合并为新的库
    删除冲突的库之后,将不同架构下的静态库再重新合并起来,取名:temp_new.a
lipo -create -output temp_new.a temp_i386.a temp_x86_64.a temp_armv7.a temp_arm64.a 

底层库比如openssl之类的冲突

如果遇到这种问题就不能用上面讲的删除冲突的.o文件了。笔者亲自用如下方法解决了前公司一个非常大的问题。也就是在集成网易云信的时候,grpc中的boringssl和云信sdk中用到的openssl冲突了。刚开始网易云信的哥们直接说搞不定,后来在笔者亲自试验下,给网易云信的哥们说了方法,结果成功了。后来他们把这个步骤写在了官方网站上。

链接[ 解决 openSSL 和 boringSSL 冲突的问题

当时的思路出发点是来自于动态库和静态库加载机制的不同,静态库是一开始就加载了,而动态库是在运行的时候才加载。从而错开了两者符号加载的时机。

打包动态库脚本如下:

#change your project name here
project_name="targetName"
#archs,include iphone (armv7, arm64) and iphone simulator (i386, x86_64)
archs="armv7 armv7s arm64"
for arch in $archs
do
    echo "building $arch..."
    if [ "$arch" = "i386" -o "$arch" = "x86_64" ]
    then
    xcrun_sdk="iphonesimulator"
    export cflags_config="-fembed-bitcode-marker"
    else
    xcrun_sdk="iphoneos"
    export cflags_config="-fembed-bitcode -Qunused-arguments"
    fi
    xcodebuild clean build ARCHS=$arch -sdk $xcrun_sdk TARGET_BUILD_DIR="./build-$arch" BUILT_PRODUCTS_DIR="./build-$arch" OTHER_CFLAGS="$OTHER_CFLAGS $cflags_config"
done
cp -rf ./build-arm64/$project_name.framework $project_name.framework
echo "generate product..."
lipo -create `find ./build-* -name $project_name` -output $project_name.framework/$project_name
echo "clean cache..."
#rm -rf ./build ./build-*
echo "done!"

一个库必须使用动态库use_frameworks!,另一个不能使用动态库

今天遇到了这个蛋疼的问题。著名的加密库libsodium和集成的另一个sdk出现了这种问题。而且这个sdk依赖了一大堆其他库,比如AF,SD。

由于这个SDK必须是动态库,那么最终他依赖的第三方库也必须用动态库的方式引入。这点自己弄了好了才得出这个结论。

并且有项目之前用过老版本的AF,并且还改了一大堆代码,这个库又用的新版AF。真实蛋疼。

解决办法:

  1. 解决掉老版本AF和新版AF:通过重命名老版本AF所有文件,这样就彻底把老版本和新版本区分开。得出的经验是,如果你决定改第三方库源码,那就马上全部重命名,因为对你而言这个库已经不是第三方库了。。重命名的过程当然是痛苦的,因为用到的地方太多,这就是前人挖坑后人踩坑。
  2. 将libsodium打包成动态库:因为libsodium使用c语言写的,这里读者需要懂点linux/unix下的交叉编译知识。用automake来实现跨平台编译。幸好这个库已经把相关的config文件以及生成iOS平台的shell脚本写好了。****但这中间有一个严重的坑,坑,坑!
    • 那就是不要去github项目主页上下载源码。因为下下来没有config文件。
    • 应该去下打包好的项目。也就是xx.tag.xxx这种格式的。
    • 然后下载下来,把iOS.sh从dist_build目录放到项目根目录下。
    • 然后执行sh iOS.sh。过一段时间,.a库就生成好了。
  3. 生成的.a库打包成动态库,大致步骤就是建一个动态库工程,把生成的静态库项目拖到动态库项目中。设置好需要暴露的头文件,然后用上面的脚步跑一遍。
  4. 把生成的动态库用到项目中。

之所有没有把源码直接拖到项目中,尝试过但是一拖进去就一直保持。后来用这种方法简单粗暴!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,755评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,629评论 18 139
  • 图文/夏天的小蘑菇 喜欢读书,喜欢写字,喜欢旅行,喜欢走走停停。这些风景图是去年夏天7月初在加拿大的爱德华王子岛和...
    夏天的小蘑菇阅读 520评论 9 12
  • 展开自己的联想,记住这下面的14对单词感觉很不错,虽然还只是记住汉字。 练习5 故事记忆法 我的故事是这样子的:我...
    书香飘溢阅读 172评论 0 0
  • 他住在大海边 等一封信 朝阳带来的光 是他一天的希望 海鸥飞过他的信箱 他在长椅上对着太阳 海风吹过 说他的信正在路上
    伍丁零阅读 165评论 0 2