簡體   English   中英

如何正確延長 iOS 應用程序的后台時間,以便 HTTP 請求不會被取消?

[英]How can I properly extend the background time of an iOS app so that an HTTP request doesn't get cancelled?

我有一個應用程序 (App1) 將WKWebView用於大部分 UI。 有這樣一種場景,從WKWebView向后端服務器發送 HTTP PUT 請求以保存一些數據。 要完成此保存操作,服務器將需要通過另一個應用程序 (App2) 的批准。 用戶通常會切換到 App2 進行批准,然后切換回 App1 以查看保存結果。 問題是,當 App1 進入后台時,它可能會導致對保存請求的響應被取消,即使在后端服務器上保存完全成功。 實際上沒有記錄任何錯誤,但我相當肯定它正在發生,因為 iOS 在應用程序在后台運行后暫停時正在終止連接。 我的想法是基於這個討論

由於批准在 App2 上保存所需的時間並沒有那么長,我想我可以嘗試延長 App1 的后台時間,並且它似乎在我測試過的時間內有效。

但是,我想知道這是否真的是最好的策略,如果是,對我的代碼是否有任何建議(例如,我是否應該將BeginBackgroundTask Task.Run ):

我以這些微軟文檔為例。

public override async void DidEnterBackground(UIApplication application)
{
    ExtendBackgroundTime(application);
}

private nint? webViewBgTaskId = null;
private CancellationTokenSource webViewBgTaskTokenSrc = null;

private void ExtendBackgroundTime(UIApplication application)
{
    // cancel the previous background task that was created in this function
    webViewBgTaskTokenSrc?.Cancel();
    webViewBgTaskTokenSrc = null;
    if (webViewBgTaskId.HasValue)
    {
        application.EndBackgroundTask(webViewBgTaskId.Value);
        webViewBgTaskId = null;
    }

    var cts = new CancellationTokenSource();
    nint taskId = default;
    taskId = application.BeginBackgroundTask(() =>
    {
        cts.Cancel();
        webViewBgTaskTokenSrc = null;
        application.EndBackgroundTask(taskId);
        webViewBgTaskId = null;
    });

    _ = Task.Run(async () =>
    {
        // For now, this is just set to 5 minutes, but in my experience,
        // the background task will never be allowed to continue for that long.
        // It's usually only about 30 seconds as of iOS 13.
        // But this at least gives it some finite upper bound.
        await Task.Delay(TimeSpan.FromMinutes(5), cts.Token);

        application.EndBackgroundTask(taskId);
        webViewBgTaskId = null;
    }, cts.Token);

    webViewBgTaskTokenSrc = cts;
    webViewBgTaskId = taskId;
}

以下代碼片段演示了注冊要在后台運行的任務:

nint taskID = UIApplication.SharedApplication.BeginBackgroundTask( () => {});

//runs on main or background thread
FinishLongRunningTask(taskID);

UIApplication.SharedApplication.EndBackgroundTask(taskID);

注冊過程將任務與唯一標識符taskID ,然后將其包裝在匹配的BeginBackgroundTaskEndBackgroundTask調用中。 為了生成標識符,我們在UIApplication object 上調用 BeginBackgroundTask 方法,然后啟動長時間運行的任務,通常在新線程上。 任務完成后,我們調用EndBackgroundTask並傳入相同的標識符。 這很重要,因為如果BeginBackgroundTask調用沒有匹配的EndBackgroundTask ,iOS 將終止應用程序。

注意:如果要在DidEnterBackground方法期間執行任務,則必須在單獨的線程上調用這些任務。 因此,示例項目使用 Task 來調用FinishLongRunningTask

Task.Factory.StartNew(() => FinishLongRunningTask(taskID));

暫無
暫無

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

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