RN - iOS端后台挂起后30s重启问题处理过程与心得
Posted iOSTianNan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RN - iOS端后台挂起后30s重启问题处理过程与心得相关的知识,希望对你有一定的参考价值。
RN版本 0.61.0
Xcdoe版本:13.3.1
Macos: 蒙特利
资料传送门
1.iOS后台运行的相关方案总结
2.iOS 后台挂起的一些坑
3.React Native iOS应用在后台状态下的相关问题
4.iOS App后台保活
5.iOS 后台永久保活,亲测有效
6.QiAppRunInBackground
现状与囧境
RN-ios端项目启动后, 频繁杀后台.基本上撑不过30s.并且毫无日志可以查看。
于此同时,由于上海疫情原因居家办公。手头仅有安卓手机,并无iOS测试手机(为了重新启用模拟器,把Macos系统升级到最高,Xcode升级到13.3.1,其中酸爽不再细表)。
在这里先说一下,
iOS模拟器可以作为测试真机使用
,在处理挂起的问题上与真机效果相同,不必担心(当然,这仅是一家之言。。。)
总结与原因
心急的小伙伴看这里就好
总结:
1.setTimeout
setInterVal
代码,是否存在在挂起状态调用的情况,如有请终止,否则30s妥妥的
2.
Animated.timing()
Animated.loop()
代码调用的时候,是否存在在挂起状态调用的情况,如有请终止,否则30s妥妥的,会出现rct.timing.gb.task
报错
3.
react-native-snap-carousel
组件的使用要注意,autoplay=true
在前台没有问题,如果在后台挂起,同样会造成rct.timing.gb.task
报错,30s妥妥的。
4
@react-native-community/netinfo
网络监听组件的问题 NetInfo.addEventListener()在后台挂起状态下,同样造成了rct.timing.gb.task
报错,如果有请处理,起码做个前后台判断。我这边移除最省事儿。
5.
GIF
图片后台挂起无关,GIF图片不会影响
6.目前RN框架的iOS项目,至少在本项目中,不使用无声音频方式,只要解决以上问题,同样可以做到长时间保活,因此,
无声音频方案并非必要(可用于配合排查问题)
看到这里本帖可以完结了。愿意看我心酸历程的可以继续看下去…
解决过程分享
一开始遇到该问题,确实毫无头绪,一时间各种猜想冒出来,也不确定处理的方向
是从性能角度
出发还是因为代码层面的Bug
?
看到这种性能消耗,是不是第一时间就的怀疑是不是功耗太大,以至于被系统Kill,一度我也是从这种角度去尝试,奈何路子没走通,浪费了一些时间。
也尝试过移除RN的JSBundle资源,直接跑iOS原生项目,确实可以保活很久。所以一段时间里,在性能层面打转许久。。。
而且,真机以及模拟器如果只是看APP效果,那么连着xcode是一点也看不出被Kill的情况,所以为了确保验证效果准确,
务必要将手机与Xcode断开验证
,
其次,xcode中一开始报错日志都是没有的
,压根儿不知道从何下手。
所以,如果你看到这里,我推荐你不管三七二十一,先集成一下手机播放无(有)声音频,这样的好处是,一旦系统杀死了APP,你可以瞬间得知,最重要的好处是(我也是得益于此)
,有错误日志了!!!
就不详细贴音频的OC代码,其实在这里就有 6.QiAppRunInBackground
这边简单贴一下调用
#pragma mark - keepAlive
- (void)applicationWillEnterForeground:(UIApplication *)application
NSLog(@"%s:应用将进入前台WillEnterForeground", __FUNCTION__);
if ([QiAudioPlayer sharedInstance].needRunInBackground)
[[QiAudioPlayer sharedInstance].player pause];
[[UIApplication sharedApplication] endBackgroundTask: self.backgroundTaskIdentifier];
- (void)applicationDidEnterBackground:(UIApplication *)application
NSLog(@"%s:应用进入后台DidEnterBackground", __FUNCTION__);
self.backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithName:kBgTaskName expirationHandler:^
if ([QiAudioPlayer sharedInstance].needRunInBackground)
[[QiAudioPlayer sharedInstance].player play];
if (self.backgroundTaskIdentifier != UIBackgroundTaskInvalid)
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];
self.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
];
音频播放的好处如上所述了,剩下的就是水磨工夫了,每个RN项目各不相同,就用排除法一个个定位即可。
顺便说一下
iOS12、iOS12以上,表现也不相同。
已经明确的是
目前iOS12系统, 基本可保活180s 、 iOS 以上系统,30s左右即被系统kill.
所以不用纠结iOS12系统的问题了。
一些报错与截图
1.
<Error Domain=RBSAssertionErrorDomain Code=2 "Assertion's invalidation time is in the past" UserInfo=IgnoreOnReconnect=true, NSLocalizedFailureReason=Assertion's invalidation time is in the past>
造成该断言失败的原因,经过大量的排查和测试结果,定位在这样一段代码
会发现,这段代码调用,如果APP在前台的时候,那是没什么大问题,一旦进入后台setTimeout由于在RN层面,其实是调用的原生的代码处理,所以导致了iOS挂起后,出现如上断言报错。
2.
Background Task 9 ("rct.timing.gb.task"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this.
这里的loop循环就是导致RN层面在后台挂起的元凶。。。。
这里也是,可以看到整理是做了个定时调用,这在APP处于前台没有问题,一旦iOS挂起到后台,那么就会引起30s重启。。。
排查笔记…
(无参考价值,仅供个人回顾查阅)
针对一部分处理, 大体思路还是通过iOS applicationDidEnterBackground
applicationWillEnterForeground
项RN发送消息的方式,让RN端监听状态来切换以上代码的处理
RN-iOS 原生向RN发送消息
不过貌似好像可以通过RN直接获取APP前后台挂起状态的API…
1.setTimeout循环打破
此处将 handler 在挂起时, cleanTimeout 即可
此处,增加状态拦截即可
2.Animated.loop()循环打破
:失败,只好移除
尝试过调用stop方法,但实际测试下来 动画是停止的,但是依然会造成闪退,这个待得空了 继续探索
3.setInterval处理
记得及时clean即可
只要及时 clearInterval 清除即可
4.autoPlay=true 问题处理,
未做兼容,属性设置初始化不可更改,可采用两个组件实例切换的方案做兼容,此处直接改为禁止自动播放
5.NetInfo.fetch() 网络监听代码, 因为不需要. 所以没做兼容,直接此处移除
以上是关于RN - iOS端后台挂起后30s重启问题处理过程与心得的主要内容,如果未能解决你的问题,请参考以下文章
RN - iOS - ScrollView联动滚动卡顿问题处理记录