项目中有个需求,要在应用切到后台时发送请求,统计应用的活跃率等,如果统计的请求失败,就调用崩溃接口想后台发送接口请求失败的具体信息;我用的是AFNetWork来发送请求,但进入后台发送完毕,大概率发送统计的请求报错,错误码基本是“53”(英文:由于应用中断请求失败),就导致崩溃接口被调用多次,给服务器增压 ; 搜了下遇到相同问题的,切到后台时,主线程被挂起,af的回调是返回主线程操作的,这样就导致发送完请求,请求被响应时,却无法回到主线程处理。想了3个解决办法:
1、有人说同步请求:但是这个没用,iOS9之前可以用同步请求,iOS9以后的都是代理或者异步回调的形式;而且即使同步,主线程被挂起,照样也是无法响应的
2、简单的,利用错误码53,来过滤掉:当统计应用活跃的接口失败时,判断错误码,为53,就不发送崩溃信息
3、利用beginBackgroundTaskWithExpirationHandler,切如后台向系统请求应用后台运行的时间:在applicationDidEnterBackground方法中开启一个后台任务:beginBackgroundTaskWithExpirationHandler,在后台任务回调里添加网络请求的代码,在应用进入前台、和网络请求完成的回调里endBackgroundTask关闭掉并释放掉请求的后台任务。具体代码如下:
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
self.taskId = [application beginBackgroundTaskWithExpirationHandler:^{
NSDate * opendate= [userDefaults objectForKey:@"beginData"];
NSDate * overDate = [NSDate date];
NSTimeInterval aTime = [overDate timeIntervalSinceDate:opendate];
NSString *allTime = [NSString stringWithFormat:@"%.0f",aTime];
NSLog(@"allTime - %@",allTime);
NSDictionary *requestDic = @{
@"staytime":allTime
};
[[AFRequestManager shareManager] postPhpApiRequestWithDictionary:requestDic andDefult:@"statistics/client/saytime" successResponse:^(id mySuccessResponse, BOOL flag) {
[application endBackgroundTask:_taskId];
_taskId = UIBackgroundTaskInvalid;
} errorResponse:^(NSError * _Nonnull error) {
[application endBackgroundTask:_taskId];
_taskId = UIBackgroundTaskInvalid;
}];
}];
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
//切入后台,用户可能长时间玩别的,所以清除推送房间号
[userDefaults setValue:nil forKey:JPushRoomNumberKey];
[userDefaults synchronize];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
NSLog(@"applicationIconBadgeNumber - %ld",(long)application.applicationIconBadgeNumber);
if (application.applicationIconBadgeNumber > 0 ) {
[application setApplicationIconBadgeNumber:0];
[JPUSHService resetBadge];
}
[application endBackgroundTask:_taskId];
_taskId = UIBackgroundTaskInvalid;
}
更多问题,欢迎加群讨论:565191947