共用方式為


Xamarin 中的 watchOS 背景工作

使用 watchOS 3 時,監看應用程式有三種主要方式可讓其資訊保持在最新狀態:

  • 使用數個新的背景工作之一。
  • 在手錶臉上有一個併發症(給予它額外的時間更新)。
  • 讓使用者釘選到應用程式到新的 Dock(其保留在記憶體中且經常更新)。

讓應用程式保持最新狀態

在討論開發人員可以保留 watchOS 應用程式數據和使用者介面目前和更新的所有方式之前,本節將探討一組典型的使用模式,以及使用者如何根據一天中的時間及其 Apple Watch 電話 之間移動(例如開車)。

以下列範例為例:

使用者如何在一整天的 i 電話 和 Apple Watch 之間移動

  1. 早上,在排隊等候咖啡時,用戶流覽 i 電話 目前的新聞幾分鐘。
  2. 離開咖啡店之前,他們迅速檢查天氣與手錶臉上的併發症。
  3. 午餐前,他們使用 i 上的 地圖 應用程式 電話 尋找附近的餐廳,並預訂預訂,以會見客戶。
  4. 在前往餐廳時,他們收到關於蘋果手錶的通知,並快速看一眼,他們知道他們的午餐預約正在遲到。
  5. 晚上,他們在i 電話 上使用 地圖 應用程式,在開車回家之前檢查交通情況。
  6. 在回家的路上,他們收到iMessage通知,他們的蘋果手錶要求他們拿起一些牛奶,他們使用快速回復功能來傳送回應“確定”。

由於使用者想要使用Apple Watch 應用程式的「快速概覽」(少於三秒)本質,因此應用程式在向用戶顯示之前,通常沒有足夠的時間擷取所需的資訊並更新其 UI。

藉由使用Apple隨附於 watchOS 3 的新 API,應用程式可以排程 背景重新 整理,並在使用者要求之前準備好所需的資訊。 以上述天氣併發症為例:

天氣併發症的範例

  1. 應用程式排程在特定時間由系統喚醒。
  2. 應用程式會擷取產生更新所需的資訊。
  3. 應用程式會重新產生其使用者介面,以反映新的數據。
  4. 當使用者一目了然地查看應用程式的 [複雜度] 時,其具有最新的資訊,而不需要使用者等待更新。

如上所述,watchOS 系統會使用一或多個工作喚醒應用程式,其中具有非常有限的集區:

watchOS 系統會使用一或多個工作喚醒應用程式

Apple 建議在應用程式完成自行更新程式之前,將它保持在其中,以充分利用這項工作(因為它對應用程式來說如此有限)。

系統會藉由呼叫委派的新 HandleBackgroundTasks 方法 WKExtensionDelegate 來傳遞這些工作。 例如:

using System;
using Foundation;
using WatchKit;

namespace MonkeyWatch.MonkeySeeExtension
{
  public class ExtensionDelegate : WKExtensionDelegate
  {
    #region Constructors
    public ExtensionDelegate ()
    {
    }
    #endregion

    #region Override Methods
    public override void HandleBackgroundTasks (NSSet<WKRefreshBackgroundTask> backgroundTasks)
    {
      // Handle background request here
      ...
    }
    #endregion
  }
}

當應用程式完成指定的工作時,它會將它標示為已完成,將它傳回給系統:

工作會藉由將它標示為已完成,以返回系統

新增背景工作

watchOS 3 引進了數個背景工作,應用程式可用來更新其資訊,確保其具有使用者開啟應用程式之前所需的內容,例如:

下列各節將詳細說明這些工作。

WKApplicationRefreshBackgroundTask

WKApplicationRefreshBackgroundTask是一般工作,可排程在未來日期喚醒應用程式:

WKApplicationRefreshBackgroundTask 在未來日期喚醒

在工作運行時間內,應用程式可以執行任何類型的本機處理,例如更新複雜時間軸,或使用 擷取一些必要的數據 NSUrlSession

WKURLSessionRefreshBackgroundTask

當資料完成下載並準備好由應用程式處理時,系統會傳送 WKURLSessionRefreshBackgroundTask

當數據完成下載時,WKURLSessionRefreshBackgroundTask

在背景下載數據時,應用程式不會繼續執行。 相反地,應用程式會排程數據的要求,然後會暫停,而系統會處理數據的下載,而只會在下載完成時重新喚醒應用程式。

WKSnapshotRefreshBackgroundTask

在 watchOS 3 中,Apple 已新增 Dock,讓使用者可以釘選他們慣用的應用程式並快速存取它們。 當使用者按下 Apple Watch 上的側邊按鈕時,將會顯示釘選的應用程式快照集資源庫。 使用者可以向左或向右撥動以尋找所需的應用程式,然後點選應用程式以將快照集取代為執行中應用程式的介面。

將快照集取代為執行中的應用程式介面

系統會定期擷取應用程式 UI 的快照集(藉由傳送 WKSnapshotRefreshBackgroundTask),並使用這些快照集填入 Dock。 watchOS 可讓應用程式有機會在取得此快照集之前更新其內容和UI。

快照集在 watchOS 3 中非常重要,因為它們會同時作為應用程式的預覽和啟動影像運作。 如果使用者在 Dock 中的應用程式上定居,它會展開至全螢幕,輸入前景並開始執行,因此快照集必須處於最新狀態:

如果使用者在 Dock 中的應用程式上定居,則會展開為全螢幕

同樣地,系統會發出 WKSnapshotRefreshBackgroundTask ,讓應用程式可以在擷取快照集之前準備 (藉由更新數據和 UI:

應用程式可以在擷取快照集之前更新數據和UI來準備

當應用程式標示 WKSnapshotRefreshBackgroundTask 完成時,系統會自動擷取應用程式的 UI 快照集。

重要

請務必在應用程式收到新數據並更新其使用者介面之後排程 WKSnapshotRefreshBackgroundTask ,否則使用者不會看到修改的資訊。

此外,當使用者收到來自應用程式的通知,並點選它以將應用程式帶到前景時,快照集也必須是最新的,因為它也會作為啟動畫面:

使用者會收到來自應用程式的通知,並點選它以將應用程式帶到前景

如果使用者已與 watchOS 應用程式互動超過一小時,它將能夠返回其默認狀態。 默認狀態可能代表不同應用程式的不同專案,而且根據應用程式的設計,它可能完全沒有默認狀態。

WKWatch 連線 ivityRefreshBackgroundTask

在 watchOS 3 中,Apple 已透過新的 WKWatchConnectivityRefreshBackgroundTask整合式監看式連線與背景重新整理 API。 使用這項新功能,i 電話 應用程式可以在背景中執行 watchOS 應用程式時,將全新的數據傳遞給其監看應用程式對應專案:

i 電話 應用程式可以在背景中執行 watchOS 應用程式時,將全新的數據傳遞給其監看應用程式對應專案

起始複雜推送、應用程式內容、傳送檔案或從 i 電話 應用程式更新使用者資訊,將會在背景喚醒 Apple Watch 應用程式。

當監看應用程式透過 WKWatchConnectivityRefreshBackgroundTask 喚醒時,它必須使用標準 API 方法從 i 電話 應用程式接收數據。

WKWatch 連線 ivityRefreshBackgroundTask 數據流

  1. 確定會話已啟用。
  2. 只要值為true,應用程式仍要處理數據,就會監視新的HasContentPending屬性。 和之前一樣,應用程式應該會保留工作,直到它完成處理所有數據為止。
  3. 當沒有其他數據要處理時(HasContentPending = false),請標示已完成的工作以將它傳回系統。 若無法這麼做,將會耗盡應用程式配置的背景運行時間,導致當機報告。

背景 API 生命週期

將所有新的背景工作 API 片段放在一起,一組典型的互動看起來如下:

背景 API 生命週期

  1. 首先,watchOS 應用程式會排程背景工作,以在未來某個時間點喚醒。
  2. 應用程式會由系統喚醒,並傳送工作。
  3. 應用程式會處理工作以完成任何必要工作。
  4. 由於處理工作,應用程式可能需要排程更多背景工作,以在未來完成更多工作,例如使用 NSUrlSession下載更多內容。
  5. 應用程式會將工作標示為已完成,並將它傳回給系統。

負責任地使用資源

監看式OS 應用程式必須藉由限制其對系統共用資源的流失,在生態系統內負責任地運作。

請檢視下列案例:

watchOS 應用程式會限制其耗盡系統的共享資源

  1. 使用者於下午 1:00 啟動 watchOS 應用程式。
  2. 應用程式會在下午 2:00 排程一小時內喚醒並下載新內容的工作。
  3. 下午 1:50 時,用戶會重新開啟應用程式,以便目前更新其數據和 UI。
  4. 應用程式應該在下午 2:50 重新排程工作一小時後執行,而不是讓工作在 10 分鐘內再次喚醒應用程式。

雖然每個應用程式都不同,但Apple建議尋找使用模式,例如上面所示的模式,以協助節省系統資源。

實作背景工作

為了方便起見,本檔會使用假的 MonkeySoccer 運動應用程式,向用戶報告足球分數。

請檢視下列一般使用案例:

一般使用案例

用戶最喜歡的足球隊正在下午 7:00 到下午 9:00 進行一場大型比賽,因此應用程式應該預期使用者會定期檢查分數,並決定 30 分鐘的更新間隔。

  1. 用戶會開啟應用程式,並在 30 分鐘後排程背景更新的工作。 背景 API 只允許在指定時間執行一種背景工作。
  2. 應用程式會收到工作並更新其數據和UI,然後排程30分鐘後的另一個背景工作。 請務必讓開發人員記得排程另一個背景工作,否則應用程式永遠不會重新叫用以取得更多更新。
  3. 同樣地,應用程式會收到工作並更新其數據、更新其 UI,並在 30 分鐘後排程另一個背景工作。
  4. 相同的程式會再次重複。
  5. 收到最後一個背景工作,應用程式會再次更新其數據和UI。 因為這是最終分數,因此不會排程新的背景重新整理。

背景更新的排程

假設上述案例,MonkeySoccer 應用程式可以使用下列程式代碼來排程背景更新:

private void ScheduleNextBackgroundUpdate ()
{
  // Create a fire date 30 minutes into the future
  var fireDate = NSDate.FromTimeIntervalSinceNow (30 * 60);

  // Create
  var userInfo = new NSMutableDictionary ();
  userInfo.Add (new NSString ("LastActiveDate"), NSDate.FromTimeIntervalSinceNow(0));
  userInfo.Add (new NSString ("Reason"), new NSString ("UpdateScore"));

  // Schedule for update
  WKExtension.SharedExtension.ScheduleBackgroundRefresh (fireDate, userInfo, (error) => {
    // Was the Task successfully scheduled?
    if (error == null) {
      // Yes, handle if needed
    } else {
      // No, report error
    }
  });
}

當應用程式想要喚醒並建立 ,以保存所要求工作的詳細數據時,它會在未來建立NSMutableDictionary新的 NSDate 30 分鐘。 的 ScheduleBackgroundRefresh 方法是 SharedExtension 用來要求排程的工作。

如果系統無法排程所要求的工作,系統將會傳回 NSError

處理更新

接下來,請仔細查看 5 分鐘視窗,其中顯示更新分數所需的步驟:

顯示更新分數所需步驟的 5 分鐘視窗

  1. 在下午 7:30:02 時,應用程式會由系統喚醒,並指定更新背景工作。 其第一個優先順序是從伺服器取得最新的分數。 請參閱 下面的排程 NSUrlSession
  2. 在 7:30:05 應用程式完成原始工作時,系統會讓應用程式進入睡眠狀態,並繼續在背景下載要求的數據。
  3. 當系統完成下載時,它會建立新的工作來喚醒應用程式,以便處理下載的資訊。 請參閱 處理背景工作處理下列下載完成
  4. 應用程式會儲存更新的資訊,並將工作標示為已完成。 開發人員目前可能會想要更新應用程式的使用者介面,不過 Apple 建議排程快照集工作來處理該程式。 請參閱 下方的排程快照集更新
  5. 應用程式會收到快照集工作、更新其使用者介面,並將工作標示為已完成。 請參閱 下方處理快照集更新

排程 NSUrlSession

下列程式代碼可用來排程下載最新的分數:

private void ScheduleURLUpdateSession ()
{
  // Create new configuration
  var configuration = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration ("com.example.urlsession");

  // Create new session
  var backgroundSession = NSUrlSession.FromConfiguration (configuration);

  // Create and start download task
  var downloadTask = backgroundSession.CreateDownloadTask (new NSUrl ("https://example.com/gamexxx/currentScores.json"));
  downloadTask.Resume ();
}

它會設定並建立新的 NSUrlSession,然後使用該工作階段,使用 CreateDownloadTask 方法建立新的下載工作。 它會呼叫 Resume 下載工作的 方法來啟動會話。

處理背景工作

藉由覆寫 HandleBackgroundTasksWKExtensionDelegate方法,應用程式可以處理傳入的背景工作:

using System;
using System.Collections.Generic;
using Foundation;
using WatchKit;

namespace MonkeySoccer.MonkeySoccerExtension
{
  public class ExtensionDelegate : WKExtensionDelegate
  {
    #region Computed Properties
    public List<WKRefreshBackgroundTask> PendingTasks { get; set; } = new List<WKRefreshBackgroundTask> ();
    #endregion

    ...

    #region Public Methods
    public void CompleteTask (WKRefreshBackgroundTask task)
    {
      // Mark the task completed and remove from the collection
      task.SetTaskCompleted ();
      PendingTasks.Remove (task);
    }
    #endregion

    #region Override Methods
    public override void HandleBackgroundTasks (NSSet<WKRefreshBackgroundTask> backgroundTasks)
    {
      // Handle background request
      foreach (WKRefreshBackgroundTask task in backgroundTasks) {
        // Is this a background session task?
        var urlTask = task as WKUrlSessionRefreshBackgroundTask;
        if (urlTask != null) {
          // Create new configuration
          var configuration = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration (urlTask.SessionIdentifier);

          // Create new session
          var backgroundSession = NSUrlSession.FromConfiguration (configuration, new BackgroundSessionDelegate (this, task), null);

          // Keep track of all pending tasks
          PendingTasks.Add (task);
        } else {
          // Ensure that all tasks are completed
          task.SetTaskCompleted ();
        }
      }
    }
    #endregion

    ...
  }
}

方法 HandleBackgroundTasks 會循環執行系統已傳送應用程式的所有 [工作] 來 backgroundTasks搜尋 WKUrlSessionRefreshBackgroundTask。 如果找到其中一個,它會重新加入會話,並附加 NSUrlSessionDownloadDelegate 以處理正在完成的下載 (請參閱 處理下方的下載完成 ):

// Create new session
var backgroundSession = NSUrlSession.FromConfiguration (configuration, new BackgroundSessionDelegate (this, task), null);

它會在工作上保留句柄,直到它完成,方法是將它新增至集合:

public List<WKRefreshBackgroundTask> PendingTasks { get; set; } = new List<WKRefreshBackgroundTask> ();
...

// Keep track of all pending tasks
PendingTasks.Add (task);

所有傳送至應用程式的工作都必須完成,對於目前未處理的任何工作,請將其標示為完成:

if (urlTask != null) {
  ...
} else {
  // Ensure that all tasks are completed
  task.SetTaskCompleted ();
}

處理下載完成

MonkeySoccer 應用程式會使用下列 NSUrlSessionDownloadDelegate 委派來處理下載完成並處理要求的數據:

using System;
using Foundation;
using WatchKit;

namespace MonkeySoccer.MonkeySoccerExtension
{
  public class BackgroundSessionDelegate : NSUrlSessionDownloadDelegate
  {
    #region Computed Properties
    public ExtensionDelegate WatchExtensionDelegate { get; set; }

    public WKRefreshBackgroundTask Task { get; set; }
    #endregion

    #region Constructors
    public BackgroundSessionDelegate (ExtensionDelegate extensionDelegate, WKRefreshBackgroundTask task)
    {
      // Initialize
      this.WatchExtensionDelegate = extensionDelegate;
      this.Task = task;
    }
    #endregion

    #region Override Methods
    public override void DidFinishDownloading (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, NSUrl location)
    {
      // Handle the downloaded data
      ...

      // Mark the task completed
      WatchExtensionDelegate.CompleteTask (Task);

    }
    #endregion
  }
}

初始化時,它會保留 和 WKRefreshBackgroundTask 繁衍它的 句柄ExtensionDelegate。 它會覆寫 DidFinishDownloading 方法來處理下載完成。 CompleteTask然後使用的 ExtensionDelegate 方法,通知工作已完成,並將它從暫止工作集合中移除。 請參閱 上述處理背景工作

排程快照集更新

下列程式代碼可用來排程快照集工作,以最新的分數更新UI:

private void ScheduleSnapshotUpdate ()
{
  // Create a fire date of now
  var fireDate = NSDate.FromTimeIntervalSinceNow (0);

  // Create user info dictionary
  var userInfo = new NSMutableDictionary ();
  userInfo.Add (new NSString ("lastActiveDate"), NSDate.FromTimeIntervalSinceNow (0));
  userInfo.Add (new NSString ("reason"), new NSString ("UpdateScore"));

  // Schedule for update
  WKExtension.SharedExtension.ScheduleSnapshotRefresh (fireDate, userInfo, (error) => {
    // Was the Task successfully scheduled?
    if (error == null) {
      // Yes, handle if needed
    } else {
      // No, report error
    }
  });
}

就像上述方法一樣 ScheduleURLUpdateSession ,它會在應用程式想要被叫醒時建立新的 NSDate ,並建立 NSMutableDictionary 來保存所要求工作的詳細數據。 的 ScheduleSnapshotRefresh 方法是 SharedExtension 用來要求排程的工作。

如果系統無法排程所要求的工作,系統將會傳回 NSError

處理快照集更新

若要處理快照集工作, HandleBackgroundTasks 方法(請參閱 上述處理背景工作 )已修改為如下所示:

public override void HandleBackgroundTasks (NSSet<WKRefreshBackgroundTask> backgroundTasks)
{
  // Handle background request
  foreach (WKRefreshBackgroundTask task in backgroundTasks) {
    // Take action based on task type
    if (task is WKUrlSessionRefreshBackgroundTask) {
      var urlTask = task as WKUrlSessionRefreshBackgroundTask;

      // Create new configuration
      var configuration = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration (urlTask.SessionIdentifier);

      // Create new session
      var backgroundSession = NSUrlSession.FromConfiguration (configuration, new BackgroundSessionDelegate (this, task), null);

      // Keep track of all pending tasks
      PendingTasks.Add (task);
    } else if (task is WKSnapshotRefreshBackgroundTask) {
      var snapshotTask = task as WKSnapshotRefreshBackgroundTask;

      // Update UI
      ...

      // Create a expiration date 30 minutes into the future
      var expirationDate = NSDate.FromTimeIntervalSinceNow (30 * 60);

      // Create user info dictionary
      var userInfo = new NSMutableDictionary ();
      userInfo.Add (new NSString ("lastActiveDate"), NSDate.FromTimeIntervalSinceNow (0));
      userInfo.Add (new NSString ("reason"), new NSString ("UpdateScore"));

      // Mark task complete
      snapshotTask.SetTaskCompleted (false, expirationDate, userInfo);
    } else {
      // Ensure that all tasks are completed
      task.SetTaskCompleted ();
    }
  }
}

方法會測試正在處理的工作類型。 WKSnapshotRefreshBackgroundTask如果是 ,它就會取得工作的存取權:

var snapshotTask = task as WKSnapshotRefreshBackgroundTask;

方法會更新使用者介面,然後建立 NSDate ,以告訴系統快照集何時過期。 它會使用使用者資訊建立 NSMutableDictionary ,以描述新的快照集,並以這項資訊標記完成的快照集工作:

// Mark task complete
snapshotTask.SetTaskCompleted (false, expirationDate, userInfo);

此外,它也會告訴快照集工作,應用程式不會返回默認狀態(在第一個參數中)。 沒有預設狀態概念的應用程式應該一律將此屬性設定為 true

有效率地工作

如上述五分鐘視窗範例所示,MonkeySoccer 應用程式透過有效率地運作及使用新的 watchOS 3 背景工作來更新分數,應用程式僅作用中 15 秒:

應用程式只作用中15秒

這樣可降低應用程式對可用 Apple Watch 資源和電池使用時間的影響,也讓應用程式能夠與在手錶上執行的其他應用程式搭配運作得更好。

排程的運作方式

當 watchOS 3 應用程式處於前景時,它一律會排程執行,而且可以執行任何類型的處理,例如更新數據或重新繪製其 UI。 當應用程式進入背景時,系統通常會暫停它,且所有運行時間作業都會停止。

當應用程式位於背景時,系統可能會以快速執行特定工作為目標。 因此,在 watchOS 2 中,系統可能會暫時喚醒背景應用程式,以執行處理長外觀通知或更新應用程式併發症等動作。 在 watchOS 3 中,有數種可在背景中執行應用程式的新方式。

當應用程式處於背景時,系統會對其施加數個限制:

  • 只需要幾秒鐘的時間才能完成任何指定的工作。 系統不僅會考慮經過的時間量,還會考慮應用程式耗用多少 CPU 能力來衍生此限制。
  • 任何超過其限制的應用程式都會以下列錯誤碼終止:
    • CPU - 0xc51bad01
    • 時間 - 0xc51bad02
  • 系統會根據要求應用程式執行的背景工作類型來施加不同的限制。 例如, WKApplicationRefreshBackgroundTaskWKURLSessionRefreshBackgroundTask [工作] 會針對其他類型的背景工作提供略長一點的運行時間。

複雜功能和應用程式 更新

除了 Apple 新增至 watchOS 3 的新背景工作之外,watchOS 應用程式的複雜功能可能會影響應用程式接收背景更新的方式和時機。

複雜功能是小型視覺元素,可一目了然地提供有用的資訊。 根據選取的手錶臉部,用戶能夠使用 watchOS 3 中手錶應用程式提供的一或多個複雜功能來自定義手錶臉部。

如果使用者在其手錶臉上包含其中一個應用程式的複雜功能,則會為應用程式提供下列更新的優點:

  • 它會導致系統讓應用程式處於可啟動狀態,並嘗試在背景啟動應用程式、將應用程式保留在記憶體中,並額外提供更新時間。
  • 併發症保證每天至少 50 個推送更新。

開發人員應一律努力為其應用程式建立令人信服的複雜功能,以吸引使用者將他們新增至手錶臉部,原因如下。

在 watchOS 2 中,複雜度是應用程式在背景中接收運行時間的主要方式。 在 watchOS 3 中,仍會確保複雜應用程式每小時收到多個更新,不過,它可以用來 WKExtensions 要求更多運行時間來更新其複雜狀況。

看看下列程式代碼,用來從連線的 i 電話 應用程式更新複雜狀況:

using System;
using WatchConnectivity;
using UIKit;
using Foundation;
using System.Collections.Generic;
using System.Linq;
...

private void UpdateComplication ()
{

  // Get session and the number of remaining transfers
  var session = WCSession.DefaultSession;
  var transfers = session.RemainingComplicationUserInfoTransfers;

  // Create user info dictionary
  var iconattrs = new Dictionary<NSString, NSObject>
    {
      {new NSString ("lastActiveDate"), NSDate.FromTimeIntervalSinceNow (0)},
      {new NSString ("reason"), new NSString ("UpdateScore")}
    };

  var userInfo = NSDictionary<NSString, NSObject>.FromObjectsAndKeys (iconattrs.Values.ToArray (), iconattrs.Keys.ToArray ());

  // Take action based on the number of transfers left
  if (transfers < 1) {
    // No transfers left, either attempt to send or inform
    // user of situation.
    ...
  } else if (transfers < 11) {
    // Running low on transfers, only send on important updates
    // else conserve for a significant change.
    ...
  } else {
    // Send data
    session.TransferCurrentComplicationUserInfo (userInfo);
  }
}

它會使用 RemainingComplicationUserInfoTransfersWCSession 屬性來查看應用程式在當天剩餘多少次優先順序傳輸,然後根據該數位採取動作。 如果應用程式開始在傳輸時執行低,它可能會阻礙傳送次要更新,而且只有在有重大變更時才會傳送資訊。

排程和停駐

在 watchOS 3 中,Apple 已新增 Dock,讓使用者可以釘選他們慣用的應用程式並快速存取它們。 當使用者按下 Apple Watch 上的側邊按鈕時,將會顯示釘選的應用程式快照集庫。 使用者可以向左或向右撥動以尋找所需的應用程式,然後點選應用程式,將快照集取代為執行中應用程式的介面。

擴充座

系統會定期擷取應用程式的UI快照集,並使用這些快照集填入 Docs。watchOS 可讓應用程式有機會在擷取此快照集之前更新其內容和UI。

已釘選到擴充座的應用程式可以預期下列各項:

  • 他們至少會收到每小時一次更新。 這包括應用程式重新整理工作和快照集工作。
  • 更新預算會在 Dock 中的所有應用程式之間散發。 因此,使用者釘選的應用程式越少,每個應用程式將會收到更多的潛在更新。
  • 應用程式會保留在記憶體中,讓應用程式在從 Dock 中選取時快速繼續。

使用者執行的最後一個應用程式會被視為 最近使用 的應用程式,並將佔用 Dock 中的最後一個位置。 用戶可以從該處選擇永久釘選到 Dock。 [最近使用] 會像使用者已釘選到 Dock 的任何其他最愛應用程式一樣處理。

重要

只新增至主畫面的應用程式將不會得到任何定期排程。 若要接收定期排程和背景更新,必須將應用程式新增至 Dock。

如本檔稍早所述,快照集在 watchOS 3 中非常重要,因為它們會同時作為應用程式的預覽和啟動影像運作。 如果使用者在 Dock 中的應用程式上定居,它會展開為全螢幕,輸入前景並開始執行,因此快照集必須處於最新狀態。

有時候系統決定它需要應用程式UI的全新快照集。 在此情況下,快照集要求不會計入應用程式的運行時間預算。 下列會觸發系統快照集要求:

  • 複雜時間軸更新。
  • 使用者與應用程式的通知互動。
  • 從前景切換至背景狀態。
  • 進入背景狀態一小時之後,應用程式就可以返回默認狀態。
  • 當 watchOS 第一次開機時。

最佳做法

使用背景工作時,Apple 會建議下列最佳做法:

  • 視需要更新應用程式的頻率排程。 每次應用程式執行時,都應該重新評估其未來需求,並視需要調整此排程。
  • 如果系統傳送背景重新整理工作,且應用程式不需要更新,請延遲工作,直到實際需要更新為止。
  • 請考慮應用程式可用的所有執行時間機會:
    • Dock 和 Foreground 啟用。
    • 通知。
    • 複雜更新。
    • 背景重新整理。
  • 用於 ScheduleBackgroundRefresh 一般用途的背景執行時間,例如:
    • 輪詢系統以取得資訊。
    • 排程未來 NSURLSessions 以要求背景數據。
    • 已知時間轉換。
    • 觸發複雜更新。

快照集最佳做法

使用快照集更新時,Apple 會提出下列建議:

  • 只有在需要時才使快照集失效,例如,當內容發生重大變更時。
  • 避免高頻率快照集失效。 例如,定時器應用程式不應該每秒更新快照集,它應該只在定時器結束時完成。

應用程式數據流

Apple 建議使用數據流的下列專案:

應用程式數據流圖

外部事件 (例如 Watch 連線 ivity) 喚醒應用程式。 這會強制應用程式更新其數據模型(代表應用程式目前狀態)。 由於數據模型變更,應用程式需要更新其複雜狀況、要求新的快照集、可能啟動背景 NSURLSession 以提取更多數據,並排程進一步的背景重新整理。

應用程式生命週期

由於 Dock 和將最愛的應用程式釘選到它的能力,Apple 認為使用者將在更多應用程式之間移動,更頻繁地移動,然後他們確實使用 watchOS 2。 因此,應用程式應該準備好處理這項變更,並在前景和背景狀態之間快速移動。

Apple 有下列建議:

  • 在進入前景啟用時,請確定應用程式會儘快完成任何背景工作。
  • 請務必先完成所有前景工作,再呼叫 NSProcessInfo.PerformExpiringActivity進入背景。
  • 在 watchOS 模擬器中測試應用程式時,不會強制執行任何工作預算,讓應用程式可以視需要重新整理,以正確測試功能。
  • 請務必在實際的Apple Watch硬體上進行測試,以確保應用程式在發佈至iTunes 連線 之前,不會執行超過其預算。
  • 蘋果建議在測試和偵錯時將蘋果手錶放在充電器上。
  • 請確定已徹底測試冷啟動和繼續應用程式。
  • 確認所有應用程式工作都已完成。
  • 變更固定在 Dock 中的應用程式數目,以測試最佳和最差的案例。

摘要

本文涵蓋 Apple 對 watchOS 所做的增強功能,以及如何用來讓手錶應用程式保持最新狀態。 首先,它涵蓋了 Apple 已在 watchOS 3 中新增的所有新背景工作。 然後,它涵蓋背景 API 生命週期,以及如何在 Xamarin watchOS 應用程式中實作背景工作。 最後,它涵蓋排程的運作方式,並提供一些最佳做法。