Me inscrevi para o 1º desafio do Golden Stone Project - compartilhe o prêmio de 100.000, este é meu 2º artigo, clique para ver os detalhes do evento
Este artigo documenta o processo de uma falha descoberta na atualização do iOS16 ontem até sua resolução.
prefácio
Ontem, no primeiro dia após o Mid-Autumn Festival, o pai da Apple empurrou o sistema iOS16.
Então, como uma operação regular dos desenvolvedores iOS, iniciei um longo caminho de atualização:
- Atualize o macOS para 12.6
- Atualizar iOS16
- Atualize o Xcode14
Execute o aplicativo e, em seguida, falhe, as informações da captura de tela da falha são as seguintes:
Simples de reproduzir o acidente
Como o Xcode14 é a versão IDE necessária apenas para o desenvolvimento contínuo subsequente (em teoria, o Xcode13 ainda pode ser usado para desenvolvimento, mas para iOS16 é melhor usar o Xcode14), fizemos uma simples reprodução estatística do problema de travamento:
Versão IDE | Versão do iOS | equipamento | Ele trava |
---|---|---|---|
Xcode14 | iOS 15 | máquina real | não |
Xcode14 | iOS 15 | emulador | não |
Xcode14 | iOS 16 | máquina real | Sim |
Xcode14 | iOS 16 | emulador | não |
Pode-se ver que o travamento ocorre apenas no dispositivo real do iOS16.
Solucionar problemas de posicionamento
De acordo com as informações, podemos descobrir que o problema de travamento ocorre na CocoaMQTT
biblioteca de dependências relacionada -- CocoaAsyncSocket
.
Então, fomos ao CocoaMQTT
topo para ver alguns problemas em aberto:
Há um problema de feedback enviado em 15 de agosto, provavelmente dizendo que há uma falha no beta5 do Xcode14, e também está envolvido CocoaAsyncSocket
.
Então, seguimos o vine e continuamos procurando a biblioteca de dependências CocoaAsyncSocket
.
Com certeza, um problema é muito atraente:
Eu acho que isso é um problema dentro da estrutura do iOS 16 Core Foundation. O código-fonte do novo Core Foundation não foi lançado, então eu apenas registrei um bug na 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 : Usando GetX, o cliente Flutter wanandroid foi refatorado.