Xcode12 + iOS14 封装framework复盘

总结下封装sdk遇到的一些问题。

目的是要封装个sdk供渠道app使用,内部会集成一些广告商sdk,然后封装一些网络请求传递调用信息,最后打包提供给客户。

功能总体很简单,考虑到需要后期维护,选了cocoapods工具作为操作集,从初始化,到demo,到打包上传均提供现成的解决方案。

问题1

pod太慢,下行速度在几kb徘徊,搜了一波答案,用SwitchHosts将git主要节点加入host ,又用git config --global http.https://github.com.proxy socks5://127.0.0.1:1086 将git代理到vpn端口上,效果立即提升。

问题2

根据说明配置好spec文件后,发现无法运行模拟器,报错如下:

Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

照着最佳答案配置后,问题解决。原因是:

苹果最新退出的m1芯片彻底排除了x86_64的指令集,从Xcode12开始,模拟器指令集也默认也包含了arm64,但因为很多第三方针对模拟器编译后的产物并不包含,所以需要将模拟器的指令集中排除arm64,设置后,模拟器将不再被认为支持arm64。

大概有以下几种方案:

方案1

 Build Settings >> Excluded Architectures added "arm64" to both Release and Debug mode for "Any iOS Simulator SDK" option.

这种方案需要将主项目和pod项目同时设置,且再次pod install后pod相关的设置会失效。

方案2

s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }

需要在pod spec里增加两行,但对于自己的pod dev项目可以,对于其它第三方项目是没有权限的,其中pod_target_xcconfig和user_target_xcconfig的区别为:

  • pod_target_xcconfig 用于当自身pod配置
  • user_target_xcconfig 用于设置调用方的配置,比如主工程,鉴于工具不可污染调用方的原则,不建议使用。所以调用方还是建议自己在Build Setting里设置为好。

方案3

post_install do |installer|

 installer.pods_project.build_configurations.each do |config|

 config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"

 end

end

在Podfile里增加以上,可以设置所有pod项目,一劳永逸,也是最终解决方案

方案4

  • 删除Valid Architectures 选项

xcode12之前Valid Architectures用于标识所有指令集的集合,通过和standard architectures搭配得到最终需要的指令集,Xcode12以后弃用Valid Architectures,推出Excluded Archs来排除不支持的指令集,显然指令集太多了,算交集不如算排除来得简单。
但最终不清楚是如何解决的问题,not work for me。

方案5

  • Setting Validate Workspace to YES
    不清楚具体含义,Xcode12开始有的选项,英文翻译为:
    If enabled, perform validation checks on the workspace configuration as part of the build process.
    https://developer.apple.com/forums/thread/669274 里有个答案说明:

Same thing happened with my project. I believe that this is an intentional change by Apple to force developers to start distributing xcframeworks with support for arm64 simulators (M1 Macs). Fat binary frameworks don't work anymore because simulators and actual devices can have the same architecture. The proper solution is to repack the GoogleCast framework into xcframework. You can do this by splitting the fat binary into two using lipo (one for simulator and one for real devices). If you don't want to do this, you can enable "Validate workspace" in build settings. This will enable you to build your project and only output a warning.

说是打开Validate workspace设置后,以上问题只会用警告的方式输出,不影响运行,但同样 not word for me。

后续查看后得知:

苹果在Xcode12.3中统一验证了framework的合法性,不在支持合成模拟器和真机的framework(因为模拟器和真机都支持arm64了),所以就会报错,但因错误类似,被归结为一个问题,有点混淆视听。
开启Validate workspace后,会将workspace错误当做警告,暂时解决问题,同样的,所有错误都会被当做警告,风险未知。
链接:https://stackoverflow.com/questions/63267897/building-for-ios-simulator-but-the-linked-framework-framework-was-built/65306886

至此 该问题解决,从搜索到的文章数量来看,Xcode12 绝大部分问题都因为m1芯片引发,吐槽者甚众,模拟器从诞生起就和真机是两码事,很多第三方服务都得通过打包合成的方式提供服务,突然被暂停影响面太大了。

----------------------开始打包----------------------

问题3

  • 隐藏.h文件private_header_files 设置后不生效。
  • 解决
    pod默认会将所有.h设为公开,设置public_header_files后将只读取其中的.h作为公开类。

问题4

  • 执行
    pod lib lint SMSDK.podspec --verbose --allow-warnings
  • 报错
    missing compatible arch in /Library/Ruby/Gems/2.6.0/gems/ffi-1.14.2/lib/ffi_c.bundle - /Library/Ruby/Gems/2.6.0/gems/ffi-1.14.2/lib/ffi_c.bundle
  • 解决
    ffi-1.14.2不支持m1芯片,命令增加arch -x86_64前缀,解决问题。通过将终端app设置为Rosetta模式无效。

Rosetta为苹果针对M1芯片推出的兼容模式

问题5

  • 执行
    pod trunk push SMSDK.podspec --allow-warnings
  • 报错
    [!] Source code for your Pod was not accessible to CocoaPods Trunk. Is it a private repo or behind a username/password on http?
  • 解决
    因为pod是私有库,私有库应使用pod repo push而不是pod trunk push,浪费不少时间,其实是因为搞错了pod库的模式,创建pod私有库其实毫无意义,但凡要给别人用,必须公开。隐蔽源代码应该再创建个git仓库才对,pod仓库只用来放编译好的framework即可。

问题6

  • 执行
    pod package SMSDK.podspec --force --exclude-deps --no-mangle --embedded
  • 报错
    fatal error:
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: Pods/build/package.a and Pods/build-sim/package.a have the same architectures (arm64) and can't be in the same fat output file
  • 解决
    其实还是和问题1一样,错误类型不同而已,起初根本不知道什么原因,执行pod package时错误不能稳定出现,后来才发现是缓存问题,每次打包前要执行pod cache clean -- all,另外执行打包时需要从git仓库拉代码,默认拉取main分支,所以版本分支的代码还要及时同步到main。

---------------------测试运行------------------------

问题7

Undefined symbols for architecture arm64
framework拖入项目后,所有引用文件对应的.m文件均编译失败,

Undefined symbols for architecture arm64

已经被前面几个问题折磨的死去活来,第一眼看到architecture arm64 想当然的以为又是指令集问题,不断的换电脑、切分支、新建项目、clean项目、删除缓存、重新打包、修改配置、编译下载,重试无数种方案的组合,新旧问题交织在一起乱作一团,简直要崩溃。
中间间或能成功运行几次,以为问题解决,万事大吉,赶紧各种备份。然而一觉醒来问题依旧,当场崩溃,完全的摸不着脉络。三天三夜,业务代码一句没动。
尝试过放弃pod工具集,用苹果最原始的方案重新开始,脚本打包,但找了几个脚本根本不能良好运行,再去debug太耗时间;还有只创建framework不创建demo,用编译产物导入到其它项目运行,也不能准确生效。
还有一些零碎的问题,比如手动拖入项目和从Link Binary With Libraies导入的具体区别;还有Genral tab下Embed的Do Not Embed ,Embed&Sign, Embed Without Signing三选项的区别和联系。

偶然在新项目里 用pod 导入了某第三方,发现对应的错误消失,想起之前项目里需要在Podflie和spec都导入pod,忘了什么原因。

--------------重新回到pod package。

  • --exclude-deps 用于剔除第三方生成。

为作为服务方framework集成第三方后难免与主项目冲突,所以为了解决冲突打包时去掉了第三方依赖,这也是为什么pod lint和pod package不报错的原因

  • --no-mangle 用于避免pod新建命名空间

默认的mangle用来提前命名类来避免冲突,第三方库的类名前都会加入统一前缀,例如:PodYourPodName_YourClass,而且--no-mangle--exclude-deps 无法拆分使用,当剔除第三方生成时 ,命名修改毫无意义;不剔除第三方,不重新命名肯定冲突。

问题8

  • 执行
    pod package SMSDK.podspec --force --embedded
  • 报错
    [!] podspec has binary-only depedencies, mangling not possible.
  • 解决
    因项目里使用了其它静态文件,无法打包成framework............卒。
    重新使用 pod package SMSDK.podspec --force --exclude-deps --no-mangle --embedded 强制打包。
    将测试项目内导入framework依赖的第三方后,所有问题解决。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 197,966评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,170评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,909评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,959评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,851评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,583评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,956评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,590评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,878评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,892评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,719评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,501评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,957评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,124评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,440评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,003评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,211评论 2 339

推荐阅读更多精彩内容