11

在我們的應用程序中,我們希望下載少量數據以響應推送通知。到目前爲止,推送通知運行正常,在後臺啓動應用程序並導致調用didReceiveRemoteNotification。直到應用程序在應用程序中發現時才執行異步代碼:didReceiveRemoteNotification:fetchCompletionHandler:

問題是,在此方法返回後,應用程序不會再獲得更多的CPU時間,直到它再次被預測爲止,因此沒有機會在後臺異步獲取該數據。

減少到最簡單的情況下,我仍然無法獲得異步代碼運行。

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { 
    [application setApplicationIconBadgeNumber:1]; 

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     [application setApplicationIconBadgeNumber:9]; 

     completionHandler(UIBackgroundFetchResultNewData); 
    }); 
} 

針對一推,應用程序在後臺啓動,並徽章計數設置爲1,但直到應用程序被從主屏幕推出的徽章數量未設置爲9。

iOS應該不會繼續運行應用程序,直到完成處理程序被調用,最多30秒?

Info.plist具有指定的遠程通知背景模式,推送有效負載包含'content-available':'1',並且我不會通過在應用程序切換器中向上滑動來退出應用程序。

要添加,我們使用解析使用下面的JavaScript發送此推送通知:

Parse.Push.send({ 
    where: installationQuery, 
    data: { 
     "content-available": 1, 
    } 
}, { success: function() {}, 
    error: function(error) {} 
}); 
+0

你試過這個:http://stackoverflow.com/questions/16295953/dispatch-after-is-limited-to-10-seconds? – anhtu

回答

10

先來here,並確保您啓用推送通知和添加的內容可用字段:

使用推送通知啓動下載 如果您的應用程序有新內容可用時,服務器將推送通知發送到用戶設備,則可以讓系統在後臺運行您的應用程序,以便它可以開始下載新的內容馬上。此背景模式的目的是儘可能減少用戶看到推送通知到應用程序能夠顯示相關內容的時間。應用程序通常在用戶看到通知的大致同一時間醒來,但仍然會給您比您可能得到的更多時間。 要支持此背景模式,請從Xcode項目中Capabilities選項卡的Background modes部分啓用Remote notifications選項。 (您也可以通過在您的應用程序的Info.plist文件中包含帶有遠程通知值的UIBackgroundModes項來啓用此支持。) 對於推送通知來觸發下載操作,通知的有效內容必須包含帶有內容的密鑰值設置爲1.當該鍵存在時,系統在後臺喚醒應用程序(或將其啓動到後臺)並調用應用程序委託的應用程序:didReceiveRemoteNotification:fetchCompletionHandler:method。您實施該方法應下載相關內容並將其集成到您的應用中。 下載任何內容時,建議您使用NSURLSession類來啓動和管理您的下載。有關如何使用此類來管理上載和下載任務的信息,請參閱URL加載系統編程指南。

接下來,是否有一個原因,你使用「dispatch_after」2秒延遲?

由於您在運行循環結束時調用「dispacth_after」,因此iOS「認爲」有沒有待處理的工作要做,並在調度該塊時將進程置於睡眠狀態,因此沒有人正在監聽它。

將其替換爲「dispatch_async」可能會解決此問題。

最後,如果你確實需要延遲,你應該告訴你的iOS需要一定的時間的背景下,這樣的 -

UIApplication *application = [UIApplication sharedApplication]; 
UIBackgroundTaskIdentifier __block backgroundTaskId = [application beginBackgroundTaskWithExpirationHandler:^{ 
    if (backgroundTaskId != UIBackgroundTaskInvalid) { 
     [application endBackgroundTask:backgroundTaskId]; 
     backgroundTaskId = UIBackgroundTaskInvalid; 
    } 
}]; 

然後做你的後臺工作。 不要忘記當你的工作完成後結束任務。打電話 -

if (backgroundTaskId != UIBackgroundTaskInvalid) { 
     [application endBackgroundTask:backgroundTaskId]; 
     backgroundTaskId = UIBackgroundTaskInvalid; 
    } 
+0

使用後臺任務是它! dispatch_after 2秒只是爲了將問題簡化爲最簡單的情況。實際上,我們將使用dispatch_async。但是這裏的主要問題是iOS似乎認爲我們在主runloop完成它的循環時完成了執行,而不是當調用完成處理程序時。通過使用後臺任務,iOS爲我們提供了運行時間並執行所需的異步操作。 – jsmeez

相關問題