我报名参与金石方案1期应战——分割10万奖池,这是我的第2篇文章,点击查看活动详情
本篇文章记录了从昨日更新iOS16发现的一个溃散问题到处理的过程。
前语
昨日中秋节后第一天上班,苹果爸爸推送了iOS16体系。
所以,作为iOS开发者的惯例操作,我开端漫长晋级之路:
- 晋级macOS到12.6
- 晋级iOS16
- 晋级Xcode14
运转App,然后溃散了,溃散的截图信息如下:
简略复现溃散状况
由于Xcode14是后续持续开发刚需的IDE版别(理论上说目前运用Xcode13也能够持续进行开发,但是对于适配iOS16,仍是Xcode14更好),咱们对溃散问题进行了简略的复现计算:
IDE版别 | iOS版别 | 设备 | 是否溃散 |
---|---|---|---|
Xcode14 | iOS 15 | 真机 | 否 |
Xcode14 | iOS 15 | 模拟器 | 否 |
Xcode14 | iOS 16 | 真机 | 是 |
Xcode14 | iOS 16 | 模拟器 | 否 |
能够看出,该溃散仅仅只在iOS16的真机上呈现。
排查定位问题
依据信息,咱们能够发现溃散的问题呈现在CocoaMQTT
相关的依靠库——CocoaAsyncSocket
。
所以咱们先去CocoaMQTT
上面去看了一些open issue:
有一个8月15日提交的反应的issue,大概是说在Xcode14的beta5上有溃散,并且也是触及CocoaAsyncSocket
。
所以乎,咱们顺藤摸瓜持续去依靠库CocoaAsyncSocket
上面去找找。
公然,一个issue非常夺目:
I think this is a problem inside iOS 16 Core Foundation framework. The source code of new Core Foundation is not released, so I just file a bug to 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的溃散过程(2022年9月16日更新)
更新完这篇文章后,我也收到了一些掘友的反应,说他们的CocoaAsyncSocket
并没有呈现溃散状况,再加上我最近也一向到Github上看有关的问题,所以整理复盘一下。
首要,我要说的是,我呈现CocoaAsyncSocket
的溃散,是由于我运用的CocoaMQTT
导致的。
下面是截取的溃散定位的代码方位,详细状况能够看这里:Crash when build by Xcode 14.0 beta 5 (14A5294e) and run on iOS 16.0 (20A5339d)
而CocoaMQTTSocke的这个backgroundOnSocket
默许属性上是true
:
由于我在自己项目里,并没有对backgroundOnSocket
进行更改,所以就调用了CocoaAsyncSocket
中的enableBackgroundingOnSocket()
办法。
咱们接着持续搜索enableBackgroundingOnSocket()
办法,所以能够看到它实质调用的是这个- (BOOL)enableBackgroundingOnSocketWithCaveat:(BOOL)caveat
办法:
最终咱们找到- (BOOL)enableBackgroundingOnSocketWithCaveat:(BOOL)caveat
针对kCFStreamNetworkServiceTypeVoIP改为PKPushTypeVoIP
的装备,真相也就大白了:
最终也便是说自动调用CocoaAsyncSocket
中的对外API- (BOOL)enableBackgroundingOnSocket;
才会呈现溃散:
这个bug现已埋藏久矣
这两天略微重视了一下CocoaAsyncSocket
的PR与issues,真的是感觉有点哭笑不得,由于好久好久以前就有大佬提交了相关PR及其Bug的严重性,甚至苦口婆心的说要赶忙更新,否则死一大片,然而官方便是没有什么动态:
感觉也是挺悲痛的,人家封闭这个issue的理由我也很震惊:
PushKit framework不支持全渠道,所以仍是用过期的API吧。而这一切的评论是在2015-2016年产生的。
一向过期一向爽,爽到溃散就好了。莫非就不能多些一点#if
区别渠道来处理吗?
Version 7.6.5 will CRASH on iOS 16 due to removedkCFStreamNetworkServiceTypeVoIP
#801
总结
在本篇,咱们处理了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:运用GetX,重构了Flutter wanandroid客户端。