最近我们在跟一个问题,其中涉及到了 App 保活的东东,此处分享记录下。
- 什么情况下我们的 App 会被干掉?
- 我们自己 App 中有哪些可能影响到它呢?
- 通过哪些手段优化这个问题咧
- 增加 MXMetricManager 检测
一、什么情况下我们的 App 会被干掉?
通过观看 Why is my app getting killed? 我们可以知道,iOS 中 App 主要有以下原因:
Why- Crashes 崩溃不言而喻
- Watchdog 看门狗 死锁
- CPU resource limit CPU 资源使用超过限制
- Memory footprint exceeded 内存占用过多, 最好是 50MB 以下
- Memory pressure exit 系统需要为前台 App 腾出位置, 自动清理
- Background task timeout 系统后台任务超时
二、我们自己 App 中有哪些可能影响到它呢?
对于 Crash 和 死锁先忽略,主要是内存占用过多和内存压力过大
- 内存占用过多
- 我们 App 中有好几处复杂页面,复杂的地图页面,一进入后台时通常都是超出 100MB 的
- 我们 App 中有进入后台连续定位的,并且定位时持续上传网络请求,此处也是相当耗电的。
- 内存压力过大, 毕竟类似很多都是 64 G 的手机,经常看看抖音和购物App 就很容易被自动清理了。
三、 通过哪些手段优化这个问题咧
本身用户手机的磁盘大小也是无法控制的,而我们自己的页面暂时是不好重构的,只通过其他的手段优化的:
- 功耗优化
- Background Fetch 的增加
- 后台任务的增加
3-1、 功耗优化
某个特殊机型上的 Energy impact3-1-1、此处的优化,主要是CPU 处理
,定位
,网络
,GPU
,而我们主要是以下:
- 优化定位逻辑去除额外的逆地理信息和轨迹距离的判断,相当于减少了定位和网络请求的
- 优化定位间隔时间,由之前的 5s 转化为 10 s
- 去除相关不需要的判断,少了CPU 处理
- 另外更改了定时器使用 GCD ,以及去除了一个常驻线程,减少了线程之间切换的损耗
3-1-2、另外在一个灰度版本中尝试了更改单次定位变成连续定位的。
- 毕竟之前高德就提供了连续定位的,但是之前不知道啥原因改成定时器的单次定位,现在分析测试来看,还是用到连续定位功耗损失更小的。
总的说来,此处我们的处理,主要是
定位优化
和CPU优化
的。
3-2、Background Fetch 的增加
Background Fetch- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//verride point for customization after application launch.
// For Background Fetch
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return YES;
}
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// Background Fetch 更新数据的处理
// TODO
completionHandler(UIBackgroundFetchResultNewData);
}
3-3、后台任务的增加
beginBackgroundTaskWithExpirationHandler
该方法为我们的应用请求额外的后台执行时间。
- (void)applicationDidEnterBackground:(UIApplication *)application {
//后台常驻定位,需要用户设置定位权限为Always
self.backgroudTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroudTask];
self.backgroudTask = UIBackgroundTaskInvalid;
}];
// TODO
}
注意 endBackgroundTask 和 beginBackgroundTaskWithExpirationHandler 的匹配
当然,如果后台执行任务超时了会触发 Background task timeout
杀死我们 App 的,文档上写了又额外的 10 分钟,但是从打印的 backgroundTimeRemaining 时间来看,只有180 秒的。
四、增加 MXMetricManager 检测
另外,我们可以通过 iOS 14 后新增的 MXBackgroundExitData提供每次应用终止时的退出计数来帮助我们了解我们的应用为何被杀死的原因。
也可以通过 MXMetricPayload
观察到一系列性能相关的数据,相当丰富,内存,耗电量,具体的功耗中的几个值都是有的。
所以此处我们增加 MXMetricManager 订阅检测其数据的。
#pragma mark - Puplic Method
/// 添加订阅
- (void)receiveReports API_AVAILABLE(ios(13.0)) {
[[MXMetricManager sharedManager] addSubscriber:self];
}
/// 移除订阅
- (void)pauseReports API_AVAILABLE(ios(13.0)) {
[[MXMetricManager sharedManager] removeSubscriber:self];
}
#pragma mark - MXMetricManagerSubscriber
/**
每天我们的应用最多只会收到一次回调,该次回调会把上一段 24 小时收集到的数据返回给我们。同时,如果在上一个 24 小时之前,存在老数据没有返回给我们的,也会在该次回调中一并返回。返回的数据会存储成数组的形式,每个数组的元素表示一天的数据
*/
- (void)didReceiveMetricPayloads:(NSArray<MXMetricPayload *> * _Nonnull)payloads API_AVAILABLE(ios(13.0)) {
[payloads enumerateObjectsUsingBlock:^(MXMetricPayload * _Nonnull payload, NSUInteger idx, BOOL * _Nonnull stop) {
// TO DO 后期定好后,传到我们服务器中的,仅仅支持 iOS 13
// NSLog(@"payload = %@", payload.DictionaryRepresentation);
}];
}
- (void)didReceiveDiagnosticPayloads:(NSArray<MXDiagnosticPayload *> * _Nonnull)payloads API_AVAILABLE(ios(14.0)) API_UNAVAILABLE(macos, tvos, watchos) {
[payloads enumerateObjectsUsingBlock:^(MXDiagnosticPayload * _Nonnull payload, NSUInteger idx, BOOL * _Nonnull stop) {
// TO DO 后期定好后,传到我们服务器中的, 仅仅支持 iOS 14
// NSLog(@"payload = %@", payload.dictionaryRepresentation);
}];
}
@end
通过 MXMetricManager
订阅,来观察真实的信息,此处功能还没真实的线上数据说明,后期持续观察中。
此处还是得上线后通过看数据来说明效果的,持续优化中。
网友评论