我的一些用户遇到了这个崩溃(据他们说,它发生在使用该应用程序 4-5 分钟后),但我自己无法重现它:
Application Specific Information:
<BKNewProcess: 0x175466c0; com.zsquare.iPadApp; pid: 5005; hostpid: -1> has active assertions beyond permitted time:
{(
<BKProcessAssertion: 0x17545c90> id: 48-3A424578-FF1D-4484-9026-B4C6A83AD7EF name: Background Content Fetching (191) process: <BKNewProcess: 0x175466c0; .com.zsquare.ijournalPad; pid: 5005; hostpid: -1> permittedBackgroundDuration: 30.000000 reason: backgroundContentFetching owner pid:48 preventSuspend preventThrottleDownUI preventIdleSleep preventSuspendOnSleep
)}
Elapsed total CPU time (seconds): 0.460 (user 0.460, system 0.000), 2% CPU
Elapsed application CPU time (seconds): 0.013, 0% CPU
Filtered syslog: None found
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0:
0 libsystem_kernel.dylib 0x362a4ff0 mach_msg_trap + 20
1 libsystem_kernel.dylib 0x362a4df4 mach_msg + 38
2 CoreFoundation 0x23fa58c4 __CFRunLoopServiceMachPort + 134
3 CoreFoundation 0x23fa3c4c __CFRunLoopRun + 1034
4 CoreFoundation 0x23ef7118 CFRunLoopRunSpecific + 518
5 CoreFoundation 0x23ef6f04 CFRunLoopRunInMode + 106
6 GraphicsServices 0x2d081ac8 GSEventRunModal + 158
7 UIKit 0x28139f14 UIApplicationMain + 142
8 SimpleList-iPad 0x0000f116 main (main.m:17)
9 libdyld.dylib 0x361e9872 start + 0
现在我查看了处理此崩溃的其他各种 SO 问题,但没有一个答案对我有帮助,所以我想我会在这里发布我自己的设置和代码。
首先,发生这种情况的功能与应在应用程序中运行的重复任务有关。为此,我在应用程序首次启动时在应用程序中重复了一个计时器:
- (void) setupRepeatTimer {
self.repeatTimer = [NSTimer scheduledTimerWithTimeInterval: 60.0 target:self selector:@selector(checkForAutomaticTaskTime:) userInfo:nil repeats: YES];
self.repeatTimer.tolerance = 1.0;
}
- (void) checkForAutomaticTaskTime: (NSTimer *) timer {
if (self.taskIdentifier) {
[[UIApplication sharedApplication] endBackgroundTask: self.taskIdentifier];
}
self.taskIdentifier = UIBackgroundTaskInvalid;
[self beginBackgroundUpdateTask];
// simplified, but there are more conditional checks here
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive && setting_enabled_for_automatic_task) {
[self startAutomaticBackup];
} else {
[self endBackgroundUpdateTask];
}
}
需要运行的备份可以是可变大小的,具体取决于用户的数据。这是通用代码:
- (void) startAutomaticBackup {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self runBackupWithCompletionBlock:^(NSString * filename) {
dispatch_async(dispatch_get_main_queue(), ^{
// finish on the main thread
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[self endBackgroundUpdateTask];
});
}];
});
}
可以肯定的是,beginBackgroundUpdateTask
和endBackgroundUpdateTask
看起来与 SO 和 Apple 指南中的代码示例完全相同:
- (void) beginBackgroundUpdateTask
{
self.taskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"CJAutoBackup" expirationHandler:^{
NSLog(@"beginBackgroundTask about to end = %lu", (unsigned long)self.taskIdentifier);
[self endBackgroundUpdateTask];
}];
}
- (void) endBackgroundUpdateTask
{
if (self.taskIdentifier) {
[[UIApplication sharedApplication] endBackgroundTask: self.taskIdentifier];
self.taskIdentifier = UIBackgroundTaskInvalid;
}
}
====
这就是我的设置。从用户描述来看,在应用程序运行 4-5 分钟后,应用程序在前台出现此崩溃报告时似乎崩溃了。如果他们禁用自动备份设置,该应用程序将再次正常工作。
这里的主要混淆是当应用程序在前台而不是后台使用它时应用程序崩溃,但错误消息谈论的是后台任务断言。这怎么可能?
另外,我可以做些什么来防止这个问题?我已经看到backgroundTimeRemaining
提到 UIApplication 的属性,但我不确定在我的示例中如何或在何处使用它。
使用 NSTimer 会导致任何并发症吗?在设备上,如果应用程序已经在后台,它似乎不会触发计时器。
感谢帮助。