簡體   English   中英

iOS背景執行指南示例的Apple編程指南?

[英]Apple programming guide for iOS background execution guide example?

所以在這個頁面上有一個關於后台執行的例子: https//developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072- CH4-SW1 ,這是一個例子:

- (void)applicationDidEnterBackground:(UIApplication *)application {

    bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{

        // Clean up any unfinished task business by marking where you
        // stopped or ending the task outright.
        [application endBackgroundTask:bgTask];

        bgTask = UIBackgroundTaskInvalid;
    }];

    // Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Do the work associated with the task, preferably in chunks.

        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    });

}

據說bgTask在類中被定義為變量。 因此,每個類(對象)實例都有一個bgTask屬性。 如果在異步塊完成之前多次調用applicationDidEnterBackground ,那么競爭條件是否存在危險? 我的意思是bgTask會改變它的值,而endBackgroundTask會被調用新的任務值,而不是舊的值?

這不是一個更好的解決方案:

__block UIBackgroundTaskIdentifier bgTask;

在調用beginBackgroundTaskWithName之前?

每個對象都有一個bgTask實例,但這是在AppDelegate ,而不是一般的VC或對象。 因此,從技術上講,只有一個bgTask實例在工作。

但這仍然會產生問題。 因為如果這個方法被調用兩次,它將覆蓋bgTask的值。 我的第一個想法是,在退出應用程序時,不止一次,以前的所有任務都將過期。 但經過測試意識到情況並非如此(這是IMO的一件好事)。 發生的事情是bgTask被覆蓋(如預期的那樣)並且新值被傳遞給第一個endBackgroundTask: call。 之后立即將bgTask設置為UIBackgroundTaskInvalid ,將其清除,並將清除的值傳遞給對endBackgroundTask:任何后續調用endBackgroundTask: 這顯然導致了一個不干凈的終止,因為並非所有唯一的id都已經結束,導致expiration處理程序在任何剩余的后台任務上執行。

話雖如此,我相信你對使用局部變量的假設是正確的。 如果你試試這段代碼(放在AppDelegate applicationDidEnterBackground:AppDelegate

__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
    // Clean up any unfinished task business by marking where you
    // stopped or ending the task outright.
    NSLog(@"Expired");
    [application endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

NSLog(@"Backgrounded: %@", @(bgTask));

// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Do the work associated with the task, preferably in chunks.
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"Done! %@", @(bgTask));
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    });
});

您將看到每個本地bgTask被分配了一個唯一值,並在10秒后正確完成(根據dispatch_after調用)。

我認為你要解決的問題如下:
應用程序被發送到Background狀態,iOS調用applicationDidEnterBackground: .
后台任務已啟動,可能需要幾分鍾時間。
在此期間,應用程序再次被激活,並再次發送到后台,再次調用applicationDidEnterBackground: ,並啟動另一個后台任務,如果它不是塊變量,則變量bgTask將被覆蓋。 這是對的。 因此, bgTask確實應該是一個塊變量。
與此問題相關的問題是,如果已啟動多個后台任務,您將如何完成后台執行。 這里給出一個例子,你如何做到這一點
我們的想法是擁有一個計算活動后台任務的變量。 一旦完成所有這些,就可以終止后台執行。

你是對的,當第二次調用時, applicationDidEnterBackground會引起問題。 但是為了第二次調用該方法,首先需要將應用程序放入前台。 所以解決方案很簡單。 只需從applicationWillEnterForeground調用您的到期處理applicationWillEnterForeground

- (void)expireBackgroundTask {
    // Clean up any unfinished task business by marking where you
    // stopped or ending the task outright.
    [application endBackgroundTask:bgTask];            
    bgTask = UIBackgroundTaskInvalid;
}

- (void)applicationDidEnterBackground:(UIApplication *)application {

    bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
        [self expireBackgroundTask];
    }];

    // Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Do the work associated with the task, preferably in chunks.

        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    });

}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [self expireBackgroundTask];
}

暫無
暫無

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

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