iOS15与iOS16中BackgroundFetch崩溃问题的修复咨询
iOS15与iOS16中的BackgroundFetch崩溃问题
崩溃日志
Monitor Type: Mach Exception Exception Type: EXC_BREAKPOINT (SIGTRAP) Exception Codes: KERN_INVALID_ADDRESS at 0x00000001df8354b0 Crashed Thread: 0 Pthread id: 23896613 Thread 0 Crashed: 0 BaseBoard -[_BSActionResponder action_sendResponse:] + 528 1 BaseBoard -[_BSActionResponder action_sendResponse:] + 520 2 BaseBoard -[BSAction sendResponse:] + 76 3 UIKitServices -[UISFetchContentInBackgroundAction sendResponse:] + 100 4 UIKitCore __91-[UIApplication _handleNonLaunchSpecificActions:forScene:withTransitionContext:completion:]_block_invoke_3 + 60 5 UIKitCore -[_UIAfterCACommitBlock run] + 72 6 UIKitCore -[_UIAfterCACommitQueue flush] + 176 7 UIKitCore _runAfterCACommitDeferredBlocks + 496 8 UIKitCore _cleanUpAfterCAFlushAndRunDeferredBlocks + 108 9 UIKitCore _UIApplicationFlushCATransaction + 72 10 UIKitCore _UIUpdateSequenceRun + 84 11 UIKitCore schedulerStepScheduledMainSection + 172 12 UIKitCore runloopSourceCallback + 92 13 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 14 CoreFoundation __CFRunLoopDoSource0 + 176 15 CoreFoundation __CFRunLoopDoSources0 + 244 16 CoreFoundation __CFRunLoopRun + 836 17 CoreFoundation CFRunLoopRunSpecific + 612 18 GraphicsServices GSEventRunModal + 164 19 UIKitCore -[UIApplication _run] + 888 20 UIKitCore UIApplicationMain + 340 21 app main (main.m:43) 22 (null) 0x00000001f694e960 0x0 + 8431921504
问题描述
在iOS15、iOS16系统中开启BackgroundFetch功能后,应用在后台发生崩溃。根据日志显示,所有崩溃均发生在后台,且崩溃位置已大致定位,但该如何修复?
原崩溃代码
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { if (self.currentCompletionHandler && self.currentCompletionHandler != completionHandler) { self.currentCompletionHandler(UIBackgroundFetchResultNoData); } self.currentCompletionHandler = completionHandler; //执行相关操作 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if (self.currentCompletionHandler) { self.currentCompletionHandler(UIBackgroundFetchResultNewData); //崩溃代码行 self.currentCompletionHandler = nil; } }); }
崩溃原因分析
核心问题是延迟调用BackgroundFetch的completionHandler,且未遵循系统任务生命周期规则:
- iOS15+对BackgroundFetch任务的生命周期管控更严格,系统会给应用一段有限的后台执行时间,超时或任务结束后,对应的
completionHandler会被系统释放,此时调用会触发野指针访问错误(日志中的KERN_INVALID_ADDRESS)。 - 将
completionHandler保存为成员变量跨任务复用的逻辑也有风险,每个BackgroundFetch任务的handler与当前任务绑定,旧任务被回收后调用旧handler同样会触发崩溃。
修复方案
1. 避免无意义延迟,操作完成后立即调用handler
BackgroundFetch要求必须尽快完成操作并调用handler,禁止用dispatch_after做无意义延迟。异步操作的回调里直接触发handler即可。
2. 用后台任务API延长执行时间(如需)
如果后台操作确实需要更长时间,必须通过beginBackgroundTaskWithName:expirationHandler:申请额外后台时间,确保handler调用时任务未被系统回收。
3. 不要保存completionHandler为成员变量
每个BackgroundFetch任务独立处理,避免跨任务复用handler。
修正后代码示例
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // 申请后台任务,防止系统提前回收当前任务 __block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithName:@"BackgroundFetchTask" expirationHandler:^{ // 超时后必须结束任务并调用handler [application endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; completionHandler(UIBackgroundFetchResultNoData); }]; // 执行实际的异步后台操作(比如网络请求、本地数据更新) [self executeBackgroundFetchOperation:^(BOOL hasNewData) { UIBackgroundFetchResult result = hasNewData ? UIBackgroundFetchResultNewData : UIBackgroundFetchResultNoData; completionHandler(result); // 操作完成后结束后台任务 if (bgTask != UIBackgroundTaskInvalid) { [application endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; } }]; } // 模拟实际后台操作的方法 - (void)executeBackgroundFetchOperation:(void(^)(BOOL hasNewData))completion { // 切换到全局队列执行耗时操作 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 这里替换成你的实际业务逻辑(比如网络请求、数据同步) [NSThread sleepForTimeInterval:2]; // 回到主线程回调结果 dispatch_async(dispatch_get_main_queue(), ^{ completion(YES); // 根据实际业务返回是否有新数据 }); }); }
补充注意事项
- 后台任务也有超时限制(一般不超过10分钟,但BackgroundFetch场景下建议控制在几十秒内),超时后系统会强制终止任务。
- 确保所有分支(成功、失败、超时)都调用
completionHandler,否则系统会降低BackgroundFetch的触发频率,甚至直接禁用该功能。
内容的提问来源于stack exchange,提问作者EverMe
相关产品推荐
相关产品推荐

