簡體   English   中英

iOS應用程序“在允許的時間之外有活躍的斷言 - 偶爾崩潰”

[英]iOS app “has active assertions beyond permitted time - occasional crashes”

我的一些用戶正在崩潰(據他們說,它發生在使用應用程序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];

            });
        }];
    });
}

可以肯定的是, beginBackgroundUpdateTaskendBackgroundUpdateTask看起來與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分鍾后,應用程序在此崩潰報告的前台崩潰。 如果他們禁用自動備份設置,該應用程序將再次正常工作。

這里的主要困惑是應用程序在應用程序在前台而不是后台使用它時崩潰,但錯誤消息會討論后台任務斷言。 怎么可能?

另外,我可以做些什么來防止這個問題? 我已經看過UIApplication的backgroundTimeRemaining屬性,但我不確定在我的例子中如何或在何處使用它。

使用NSTimer會導致任何並發症嗎? 在設備上,如果應用程序已經在后台,它似乎不會觸發計時器。

感謝幫助。

這是一個線程問題。 正如您所懷疑的那樣,問題確實是開始/結束后台任務調用的因子分解和體系結構。 您正在嘗試將一個后台任務標識符維護為屬性 ,然后無論實際任務花費多長時間(在后台線程上),您都會每60秒重復更改一次。 這種令人困惑的偽循環體系結構導致您的后台任務與其標識符不同步,因此后台任務的時間到期,而您的調用endBackgroundTask沒有適當的標識符。

您需要修改此體系結構,以便每個任務都有一個后台任務標識符,從而使所有內容保持獨立。 我想你會發現最簡單的方法是將每個自動備份表示為一個單獨的NSOperation。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM