web-dev-qa-db-ja.com

Apple Watchの合併症データを更新するためのフローは何ですか?

私は、合併症を設定する方法を学ぶためにインターネット上の多くのチュートリアルに従ってきました。期待通りに合併症を設定しても問題ありません。

最初のタイムラインエントリが期限切れになるまで。 12時間後、合併症を維持するために更新する方法がわかりません。以下にあるすべてのものを共有します。誰かが私に記入するのを手伝ってくれることを願っています。

ここでは、合併症で表示したいデータの変数を作成します。

struct data = {
var name: String
var startString: String
var startDate: NSDate
}

次の配列は、このデータのコンテナです。

var dataArray = [data]

これにより、時計がロックされているときに合併症を示すことができます。

func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {
    handler(.ShowOnLockScreen)
}

これにより、合併症のタイムトラベルを進めることができます。

func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) {
    handler([.Forward])
}

ここでは、タイムラインの開始時刻を現在と同じに設定しました。

func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
    handler(NSDate())
}

ここでは、タイムラインの終了時刻を今から12時間に設定しました。

func getTimelineEndDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
    handler(NSDate(timeIntervalSinceNow: (60 * 60 * 12)))
}

ここでは、合併症のテンプレートを作成します。これは、ユーザーが時計ですべての合併症を閲覧しているときに私の合併症を見たときに、サンプルデータを表示するためのものです。

func getPlaceholderTemplateForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTemplate?) -> Void) {

    let headerTextProvider = CLKSimpleTextProvider(text: "Some Data")
    let body1TextProvider = CLKSimpleTextProvider(text: "Some Data Time")
    let template = CLKComplicationTemplateModularLargeStandardBody()
    template.headerTextProvider = headerTextProvider
    template.body1TextProvider = body1TextProvider

    handler(template)
}

これにより、合併症の最初のタイムラインエントリが作成されます。コンプリケーションが有効になるとすぐに、このコードが実行され、それに応じてコンプリケーションにすぐにデータが入力されます。

func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimelineEntry?) -> Void) {

    createData()

    if complication.family == .ModularLarge {

        if dataArray.count != 0 {

            let firstData = dataArray[0]
            let headerTextProvider = CLKSimpleTextProvider(text: firstData.name)
            let body1TextProvider = CLKSimpleTextProvider(text: firstData.startString)
            let template = CLKComplicationTemplateModularLargeStandardBody()
            template.headerTextProvider = headerTextProvider
            template.body1TextProvider = body1TextProvider
            let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(), complicationTemplate: template)
            handler(timelineEntry)
        } else {
            let headerTextProvider = CLKSimpleTextProvider(text: "No Data")
            let body1TextProvider = CLKSimpleTextProvider(text: "Create some data")
            let template = CLKComplicationTemplateModularLargeStandardBody()
            template.headerTextProvider = headerTextProvider
            template.body1TextProvider = body1TextProvider

            let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(), complicationTemplate: template)
            handler(timelineEntry)
        }

    } else {
        handler(nil)
    }

}

ここで、現在持っているすべてのデータのタイムラインエントリを作成します。

func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {

    createData()

    var entries = [CLKComplicationTimelineEntry]()

    for dataObject in dataArray {

        if entries.count < limit && data.startDate.timeIntervalSinceDate(date) > 0 {

            let headerTextProvider = CLKSimpleTextProvider(text: dataObject.name)
            let body1TextProvider = CLKSimpleTextProvider(text: dataObject.startString)
            let template = CLKComplicationTemplateModularLargeStandardBody()
            template.headerTextProvider = headerTextProvider
            template.body1TextProvider = body1TextProvider
            let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(timeInterval: (-10*60), sinceDate: data.startDate), complicationTemplate: template)
            entries.append(timelineEntry)

        }

    }

    handler(entries)

}

これにより、合併症データをいつ更新するかが時計に通知されます。

func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) {
    handler(NSDate(timeIntervalSinceNow: 60 * 60 * 6))
}

これは私が問題に直面しているところです。

新しいデータを作成してタイムラインをリロードするにはどうすればよいですか?流れは何ですか?私はタイムラインを延長しようとしているのではなく、完全に置き換えるつもりです。私は完全に途方に暮れています。 Appleのドキュメント この点に関してはかなり曖昧です。次のメソッドを実装する必要があることは知っていますが、その方法がわかりません。誰かが私がこのコードを記入するのを手伝ってもらえますか?

func requestedUpdateDidBegin() {
    createData() //I assume createData() goes here? If so, how do I populate the new timeline entries based on the results?
}

func requestedUpdateBudgetExhausted() {
    //This can't possibly be the case as I haven't gotten it to work once.
}

func reloadTimelineForComplication(complication: CLKComplication!) {
      //This method appears to do nothing.
}

更新:

El Teaのおかげで、私はそれを機能させることができました。 CLKComplicationServerのインスタンスをrequestedUpdateDidBeginに追加し、reloadTimelineメソッドを内部に配置する必要があります。

更新されたコードは次のとおりです。

func requestedUpdateDidBegin() {
    print("Complication update is starting")

    createData()

    let server=CLKComplicationServer.sharedInstance()

    for comp in (server.activeComplications) {
        server.reloadTimelineForComplication(comp)
        print("Timeline has been reloaded!")
    }

}

func requestedUpdateBudgetExhausted() {
    print("Budget exhausted")
}
20
bkwebhero

合併症のリフレッシュの流れ それは時間間隔で行われています 次の順序に従います。

  • iOSは関数をrequestedUpdateDidBegin()またはrequestedUpdateBudgetExhausted()と呼びます(予算が使い果たされた場合、実行時間が長くなるまで何もしないと更新されます)。
  • requestedUpdateDidBegin()の内部 君はreloadTimelineForComplication()またはextendTimelineForComplication()を呼び出して、リロードする合併症またはデータを追加する合併症を指定する必要があります。これを行わないと、何も起こりません!
  • reloadまたはextendのどちらを呼び出したかに応じて、iOSはgetCurrentTimelineEntryForComplication()getTimelineEntriesForComplication()の一方または両方を呼び出します。
  • 合併症を更新したかどうかに関係なく、iOSはgetNextRequestedUpdateDateWithHandler()を呼び出して、次に上記の手順を繰り返すタイミングを見つけます。

注:最後の2つの手順は、必ずしもこの順序で行う必要はありません。

このプロセスはこのように機能するため、iOSは同じデータを繰り返し再生成するように要求しません。 requestedUpdateDidBegin()で、合併症を更新する必要があるかどうかを判断する機会が与えられます。そうでない場合は、コードが返されるはずです。 (これにより、コンプリケーションの実行時間が短縮され、iOSが1日の予算を使用したためにアプリが更新されなくなるのを防ぐことができます)。ただし、新しいデータがある場合は、reloadTimelineForComplication()またはextendTimelineForComplication()を呼び出してiOSに通知する必要があります。

私の知る限り、requestedUpdateDidBegin()内でリロードや拡張を要求していなかった以外は、そこに書いたものはすべて良さそうです。複雑な部分がウォッチフェイスの複数の位置に表示されたり、テンプレートごとに表示動作が異なる可能性があるため、すべてを無効にする必要があります。これが私のコードがどのように見えるかです:

_func requestedUpdateDidBegin() {

    //Not shown: decide if you actually need to update your complication.
    //If you do, execute the following code:

    let server=CLKComplicationServer.sharedInstance()

    for comp in (server.activeComplications) {
        server.reloadTimelineForComplication(comp)
    }
}
_

時間間隔の他に、プッシュアラート、ウォッチアプリの実行時にリロードを実行する、またはWCSessionでWatch Connectivityフレームワークを使用して、電話アプリに更新データを送信させ、transferCurrentComplicationUserInfo()詳細については、Appleのドキュメントの「合併症データの更新」を参照してください

私は、10分という短い更新間隔をテストするシミュレーターで成功しました。実行時間の予算があるため、実際の時計ではそれほど頻繁に更新するべきではありませんが、これにより、12時間待たずにコードをテストできます。

22
El Tea

El Teaの回答 watchOS2のコンプリケーションを更新する方法について詳しく説明します。

WatchOS 3では、合併症を最新の状態に保つための推奨される方法は、 バックグラウンド更新アプリタスク を使用することです。一連のバックグラウンドタスクを使用して、 スケジュール および ハンドル アプリ拡張機能がバックグラウンドでウェイクアップされ、次のことができます。

  • 新しいデータを取得する

  • データが到着したらモデルを更新し、
  • モデルから利用可能な新しいデータを表示するために(タイムラインをリロードまたは延長することによって)複雑さを更新し、最後に
  • アプリのドックスナップショットを更新して、ドックのデータを表示します

これは、データのフェッチやモデルの更新にコンプリケーションの1日の実行予算を使用しないため、はるかに機能的でエネルギー効率が高くなります。

また、要求にただちに応答することだけを目的とした複雑なデータソースでデータを非同期にフェッチしようとする、アドバイスされていないアプローチによる複雑さを回避します。

詳細情報、およびWWDCビデオとサンプルコードへのリンクを提供しました 別の回答で

WatchOS3の変更を要約するには

getNextRequestedUpdateDateWithHandler()の代わりにスケジュールされたバックグラウンドタスクを使用します。

requestedUpdateDidBegin()内ではなく、アプリタスクでタイムラインを再読み込みまたは延長します。

13
user4151918