Ich habe mich für die 1. Herausforderung des Golden Stone Project angemeldet - teilen Sie den Preispool von 100.000, dies ist mein 2. Artikel, klicken Sie hier, um die Details der Veranstaltung anzuzeigen
Dieser Artikel dokumentiert den Prozess von einem Absturz, der gestern im iOS16-Update entdeckt wurde, bis zu seiner Lösung.
Vorwort
Gestern, am ersten Tag nach dem Mittherbstfest, hat Apples Vater das iOS16-System gepusht.
Als regulärer Betrieb von iOS-Entwicklern habe ich also einen langen Upgrade-Weg begonnen:
- Aktualisieren Sie macOS auf 12.6
- Aktualisieren Sie iOS16
- Aktualisieren Sie Xcode14
Führen Sie die App aus und stürzen Sie dann ab. Die Screenshot-Informationen des Absturzes lauten wie folgt:
Einfach den Absturz zu reproduzieren
Da Xcode14 die IDE-Version ist, die nur für die spätere kontinuierliche Entwicklung benötigt wird (theoretisch kann Xcode13 immer noch für die Entwicklung verwendet werden, aber für iOS16 ist es besser, Xcode14 zu verwenden), haben wir eine einfache Reproduktionsstatistik des Absturzproblems erstellt:
IDE-Version | iOS-Version | Ausrüstung | Stürzt es ab |
---|---|---|---|
Xcode14 | iOS 15 | echte Maschine | nein |
Xcode14 | iOS 15 | Emulator | nein |
Xcode14 | iOS 16 | echte Maschine | Ja |
Xcode14 | iOS 16 | Emulator | nein |
Es ist ersichtlich, dass der Absturz nur auf dem realen Gerät von iOS16 auftritt.
Beheben Sie Positionierungsprobleme
Den Informationen zufolge können wir feststellen, dass das Absturzproblem in der CocoaMQTT
zugehörigen Abhängigkeitsbibliothek auftritt -- CocoaAsyncSocket
.
Also gingen wir nach CocoaMQTT
oben, um einige offene Probleme zu sehen:
Am 15. August wurde ein Feedback-Problem gemeldet, das wahrscheinlich besagt, dass es einen Absturz auf Beta5 von Xcode14 gibt, und es ist auch beteiligt CocoaAsyncSocket
.
Also folgten wir der Rebe und suchten weiter nach der Abhängigkeitsbibliothek CocoaAsyncSocket
.
Sicher genug, ein Problem ist sehr auffällig:
Ich denke, dies ist ein Problem innerhalb des iOS 16 Core Foundation-Frameworks. Der Quellcode der neuen Core Foundation ist nicht veröffentlicht, also melde ich einfach einen Fehler bei Apple (FB11489606).
根据反馈者的意见:认为这个bug可能是由于iOS16架包中的Core Foundation framework导致。
于是我们又顺带看了看CocoaAsyncSocket
的PR:
第一个PR就格外醒目!解决iOS16在后台的崩溃问题。
虽然这个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中就有反馈这个问题:
但是,在最新的2020年12月14日的CocoaAsyncSocket
的7.6.5
版本中依旧还是这么写的:
既然kCFStreamNetworkServiceTypeVoIP
已经过期了,那么我就用issuse 402
里面提到的PKPushTypeVoIP
替换一下试试。
编译,运行,App没有崩溃!!!
将过期的kCFStreamNetworkServiceTypeVoIP改为使用PKPushTypeVoIP才是解决问题的关键!!!
总结
在本篇,我们解决了CocoaAsyncSocket
在iOS16系统上的崩溃问题,其实没有太多技巧而言。
我们首先通过Xcode崩溃的信息,基本定位到了CocoaAsyncSocket
,然后在通过Github中的issues
和PR
,了解到了相关API的替换,最后发现kCFStreamNetworkServiceTypeVoIP
已经过期了,使用之前已经有大佬提出的方案,就解决了这个问题。
还记得我们之前简单统计吗?崩溃只在iOS16的真机出现,而且有开发者认为是iOS16 SDK的Bug导致。
而我通过替换kCFStreamNetworkServiceTypeVoIP改为PKPushTypeVoIP解决这个问题后,我更倾向于这个观点:
在iOS16 SDK中,可能kCFStreamNetworkServiceTypeVoIP
真的失效了,没有意义了,所以继续使用kCFStreamNetworkServiceTypeVoIP并不能完成配置,所以导致了崩溃。
到这篇文章发布之前,我已经PR了代码到CocoaAsyncSocket
,至于会不会被采纳,那就不知道了。
考虑到涉及使用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 : Mit GetX wurde der Flutter-Wanandroid-Client umgestaltet.