iOS16 システムで CocoaAsyncSocket がクラッシュする問題を解決

ゴールデン ストーン プロジェクトの最初のチャレンジにサインアップしました - 賞金プール 100,000 を共有します。これは私の 2 回目の記事です。クリックしてイベントの詳細を表示します

この記事では、昨日の iOS16 アップデートで発見されたクラッシュから解決までのプロセスについて説明します。

序文

昨日、中秋節の翌日、アップルの父親がiOS16システムをプッシュしました。

そこで、iOS 開発者の通常の作業として、長いアップグレード ロードを開始しました。

  • macOS を 12.6 にアップグレードする
  • iOS16にアップグレード
  • Xcode14 をアップグレードする

アプリを実行してからクラッシュします。クラッシュのスクリーンショット情報は次のとおりです。

画像.png

クラッシュの再現が簡単

Xcode14 は、その後の継続的な開発に必要な IDE バージョンであるため (理論的には、Xcode13 を引き続き開発に使用できますが、iOS16 では Xcode14 を使用することをお勧めします)、クラッシュの問題の簡単な再現統計を作成しました。

IDE バージョン iOS版 装置 クラッシュしますか
Xcode14 iOS15 実機 番号
Xcode14 iOS15 エミュレータ 番号
Xcode14 iOS16 実機 はい
Xcode14 iOS16 エミュレータ 番号

クラッシュは iOS16 の実機でのみ発生していることがわかります。

配置に関する問題のトラブルシューティング

CocoaMQTT情報によると、関連する依存ライブラリでクラッシュの問題が発生していることがわかります-- CocoaAsyncSocket

CocoaMQTTそこで、いくつかの未解決の問題を確認するためにトップに行きました。

画像.png

8 月 15 日に提出されたフィードバックの問題がありますが、おそらく Xcode14 の beta5 でクラッシュが発生しているというもので、それも関係していCocoaAsyncSocketます。

そのため、つるをたどり、依存ライブラリを探し続けましたCocoaAsyncSocket

案の定、問題は非常に目を引くものです:

画像.png

これは iOS 16 Core Foundation フレームワーク内の問題だと思います。新しい Core Foundation のソース コードは公開されていないため、Apple にバグを報告するだけです (FB11489606)。

根据反馈者的意见:认为这个bug可能是由于iOS16架包中的Core Foundation framework导致。

于是我们又顺带看了看CocoaAsyncSocket的PR:

画像.png

第一个PR就格外醒目!解决iOS16在后台的崩溃问题。

画像.png

虽然这个PR还没有合并,但是对于我们App开始连接MQTT就崩溃的情况还是值得试一试的,于是我们立即在Pod的源码中对这里进行了修改。

修改后,MQTT正常工作,也没有崩溃了。

难道你觉得到这里已经完了?并没有,我们接着往下看。

深入:kCFStreamNetworkServiceTypeVoIP过期导致的崩溃

我特地去看了一下有关kCFStreamNetworkServiceTypeVoIP的代码,其介绍如下:

/* deprecated network service type: */

CFN_EXPORT const CFStringRef kCFStreamNetworkServiceTypeVoIP       CF_DEPRECATED(10_7, 10_11, 4_0, 9_0, "use PushKit for VoIP control purposes");   // voice over IP control - this service type is deprecated in favor of using PushKit for VoIP control
复制代码

kCFStreamNetworkServiceTypeVoIP这个常量实际上早在iOS9就已经过期了。

甚至2016年,在CocoaAsyncSocket中Close的issue中就有反馈这个问题:

Snip20220914_8.png

但是,在最新的2020年12月14日的CocoaAsyncSocket7.6.5版本中依旧还是这么写的:

Snip20220914_9.png

既然kCFStreamNetworkServiceTypeVoIP已经过期了,那么我就用issuse 402里面提到的PKPushTypeVoIP替换一下试试。

画像.png

编译,运行,App没有崩溃!!!

将过期的kCFStreamNetworkServiceTypeVoIP改为使用PKPushTypeVoIP才是解决问题的关键!!!

总结

在本篇,我们解决了CocoaAsyncSocket在iOS16系统上的崩溃问题,其实没有太多技巧而言。

我们首先通过Xcode崩溃的信息,基本定位到了CocoaAsyncSocket,然后在通过Github中的issuesPR,了解到了相关API的替换,最后发现kCFStreamNetworkServiceTypeVoIP已经过期了,使用之前已经有大佬提出的方案,就解决了这个问题。

还记得我们之前简单统计吗?崩溃只在iOS16的真机出现,而且有开发者认为是iOS16 SDK的Bug导致

而我通过替换kCFStreamNetworkServiceTypeVoIP改为PKPushTypeVoIP解决这个问题后,我更倾向于这个观点:

在iOS16 SDK中,可能kCFStreamNetworkServiceTypeVoIP真的失效了,没有意义了,所以继续使用kCFStreamNetworkServiceTypeVoIP并不能完成配置,所以导致了崩溃。

到这篇文章发布之前,我已经PR了代码到CocoaAsyncSocket,至于会不会被采纳,那就不知道了。

画像.png

考虑到涉及使用CocoaAsyncSocket的App与第三库众多,也希望官方大佬早点解决这个问题吧。

参考文档

使用 CocoaAsyncSocket “kCFStreamNetworkServiceTypeVoIP is deprecated in iOS 9 ” warning 解决方案

kCFStreamNetworkServiceTypeVoIP is deprecated in iOS 9 warning

fix crash of backgrouding in iOS16

自己写的项目,欢迎大家star⭐️

RxStudy:RxSwift/RxCocoa框架,MVVM模式编写wanandroid客户端。

GetXStudy : GetX を使用して、Flutter wanandroid クライアントがリファクタリングされました。

Guess you like

Origin juejin.im/post/7143124820811579423