2012-08-22 85 views

回答

13

我用下面的代碼爲後臺任務處理:

__block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 

    NSLog(@"Background Time:%f",[[UIApplication sharedApplication] backgroundTimeRemaining]); 

    [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; 

    backgroundTaskIdentifier = UIBackgroundTaskInvalid; 
}]; 
+1

[self endBackgroundTask]方法做什麼?什麼是自我? – ozgur

+0

@ozgurv:更新後的代碼。謝謝 – Vardhan

1

您應該在beginBackgroundTaskWithExpirationHandler之後運行任務,或者在應用程序將狀態更改爲背景時捕獲通知,然後取消當前任務並使用beginBackgroundTaskWithExpirationHandler重新運行。

95

儘管它的名字,beginBackgroundTaskWithExpirationHandler:實際上並不「開始」一項任務。它可能會更好地被認爲是「註冊...」而不是「開始......」。你只是告訴系統,你正在做一些想要完成的事情,如果沒有問題的話。

幾點:

  • 在幾乎所有情況下,你要調用beginBackgroundTaskWithExpirationHandler:當你開始做你想要做的事,然後endBackgroundTask:時,即可大功告成。在用戶按下主頁按鈕時,您幾乎從不會調用它們(除非這是您開始執行任務時的重點,例如將某些內容保存到服務器)。

  • 您可以一次打開多個「後臺任務」。他們沒有花費。他們就像保留計數一樣。只要你還有一個開放的(「開始」沒有達到它的「結束」),那麼系統會認爲這個請求有更多的時間。調用「開始」和「結束」方法的代價非常小,因此使用這些來包含任何需要額外時間完成的任何內容。

  • 無法確定您是否會完成同步。這些方法只是提出請求。操作系統可能仍然拒絕該請求。任何時候當操作系統需要一些額外的資源時,操作系統仍可能會殺死你操作系統並非無限耐心;如果你花費的時間太長(通常約10分鐘),它會在你呼叫你的到期處理程序之後無論如何殺死你。操作系統可能會因您的手機關閉而導致您死亡。你的應用程序必須能夠處理不完成。操作系統只是給你這種能力,以便你可以改善用戶體驗。

+16

你的回答是完全真棒,thanx男人。只是一個更新:自iOS 7以來,只有3分鐘用於後臺任務,而不是10。 –

+0

建議在應用程序背景上使用beginBackgroundTaskWithExpirationHandler掃描藍牙設備嗎? – theFool

+0

藍牙後臺掃描通常更好地通過註冊後臺模式藍牙中央完成。掃描通常不屬於「只需要多一點時間來完成這個」陣營。 –

8

以下是我用beginBackgroundTaskWithExpirationHandler,包括調用該方法在後臺完成。這包括啓動新的異步任務的代碼。所以不完全是問題中提出的問題。添加以下代碼,想有人可能會尋找這樣的場景:

- (void)didReceiveObjList:(CFDataRef)message 
{ 
    // Received Object List. Processing the list can take a few seconds. 
    // So doing it in separate thread with expiration handler to ensure it gets some time to do  the task even if the app goes to background. 

    UIApplication *application = [UIApplication sharedApplication]; 
    __block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ 
    [application endBackgroundTask:bgTask]; 
    bgTask = UIBackgroundTaskInvalid; 
}]; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     [self processObjList:message]; 

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

    NSLog(@"Main Thread proceeding..."); 

} 
5

在這個頁面看看,蘋果描述瞭如何保持iPhone應用程序沒有中止,而它在後臺。 Apple Documentation

這裏就是我實現:

UIBackgroundTaskIdentifier bgTask; 

- (void)applicationDidEnterBackground:(UIApplication *)application 
{ 
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 
    NSLog(@"=== DID ENTER BACKGROUND ==="); 
    bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
     NSLog(@"End of tolerate time. Application should be suspended now if we do not ask more 'tolerance'"); 
     // [self askToRunMoreBackgroundTask]; This code seems to be unnecessary. I'll verify it. 
    }]; 

    if (bgTask == UIBackgroundTaskInvalid) { 
     NSLog(@"This application does not support background mode"); 
    } else { 
     //if application supports background mode, we'll see this log. 
     NSLog(@"Application will continue to run in background"); 
    } 
} 

/* 

- (void)askToRunMoreBackgroundTask 
{ 
    [[UIApplication sharedApplication] endBackgroundTask:bgTask]; 
    NSLog(@"restart background long-running task"); 
    bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
     NSLog(@"End of tolerate time. Application should be suspended now if we do not ask more 'tolerance'"); 
     [self askToRunMoreBackgroundTask]; 
    }]; 

} 

*/ 

- (void)applicationWillEnterForeground:(UIApplication *)application 
{ 
    NSLog(@"=== GOING BACK FROM IDLE MODE ==="); 
    //it’s important to stop background task when we do not need it anymore 
    [[UIApplication sharedApplication] endBackgroundTask:UIBackgroundTaskInvalid]; 
} 
3

下面是關於當應用程序會爲背景,我使用的是其他的答案略有變化,我需要在做些什麼主線程:

- (void)applicationWillResignActive:(UIApplication *)application 
{ 
    UIApplication *app = [UIApplication sharedApplication]; 

    // Register auto expiring background task 
    __block UIBackgroundTaskIdentifier bgTaskId = 
     [app beginBackgroundTaskWithExpirationHandler:^{ 
     [app endBackgroundTask:bgTaskId]; 
     bgTaskId = UIBackgroundTaskInvalid; 
    }]; 

    // Execute background task on the main thread 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // ------------------ 
     // DO SOMETHING INVOLVING THE WEBVIEW - WHICH MUST OCCUR ON THE MAIN THREAD! 
     // ------------------ 
     [app endBackgroundTask:bgTaskId]; 
     bgTaskId = UIBackgroundTaskInvalid; 
    }); 
} 
相關問題