我的一些用戶正在發生這種崩潰(據他們說,使用應用程序4-5分鐘後會發生這種情況),但我無法自行重現:iOS應用程序「有超出允許時間的主動斷言 - 偶爾發生崩潰」
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
現在我已經看了,與此崩潰對付其它各種做題,但沒有一個答案已經出現了對我很有幫助,所以我想我會在這裏發表我自己的設置和代碼。
首先,發生這種情況的功能與應該在應用程序中運行的重複任務有關。對於這一點,我有一個計時器在應用程序重複第一次啓動應用程序時:
- (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和蘋果指南:
- (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分鐘後,該應用程序在前臺出現崩潰報告時崩潰。如果他們禁用自動備份設置,則應用程序會再次正常工作。
這裏的主要困惑是應用程序崩潰時,應用程序在前臺使用它,而不是背景,但錯誤消息談論後臺任務斷言。這怎麼可能?
另外,我能做些什麼來防止這個問題呢?我見過UIApplication的backgroundTimeRemaining
屬性,但我不確定在我的示例中如何或在哪裏使用它。
使用NSTimer是否會導致任何併發症?在設備上,如果應用程序已經在後臺,它似乎不會觸發計時器。
欣賞幫助。
謝謝。計時器應該在任何現有的標識符上調用'endBackgroundTask',並在計時器開始時將其標記爲無效,然後開始另一個任務,那麼這仍然是一個問題?再看一遍,它看起來問題可能是'備份'過程可能需要60秒以上,所以當它完成並調用完成塊時,它會在過期的標識符上調用'endBackgroundTask'?會產生相同的問題和堆棧跟蹤,還是你認爲它仍然有一些標識符沒有得到'endBackgroundTask'的問題? –
我想我們說的是同樣的事情。看,我無法弄清楚你的代碼是幹什麼的,我也不認爲你可以。但是我們確實知道您只有一個標識符,但您可以同時執行多個備份任務。這是瘋狂的,即使_never_發生了(聽起來像在你的測試中沒有)。因此我的建議是:每個備份都是自己的NSOperation,它有自己的後臺任務和自己的後臺任務標識符。沒有更多的「循環」!你的代碼會更簡單。 – matt
我同意一般觀點,我認爲我看到了問題。解決辦法是從NSTimer函數中取出taskIdentifier,並且只調用它來環繞實際的備份功能(同時添加一個布爾值以防止在備份運行時調用備份代碼)。那樣,一次只有一個背景任務正在進行。 –