2017-09-07 10 views
19

私はかなり長い間この質問に対する答えを探していましたので、私はそれを投稿するためにいくつかの下降声明を出すつもりです。WatchKitエクステンションのAppleサンプルコードRefresh

基本的に、私はアップルのウォッチバックグラウンドリフレッシュのサンプルコードを実際に動作させるようにしたいと思っています(下のリンクとコード)。

私は、シミュレータとApple Watch Series 2を搭載したiPhone 6の両方で試してみました。バックグラウンドタスクは、時間が更新されるポイントまで決して正常に完了しません。私はドックに時計アプリを固定しようとしましたが、私はフォアグラウンドでアプリを保持し、シミュレータと実際の時計の両方で、バックグラウンドに送信しようとしました。私はXcodeやApple Watchがそれを動作させるアップデートを受け取るかどうかを知るために、ほぼ一年待ってみました。

アップルが提供するコードを正常に修正した人はいますか?

現在地全体の実行可能なサンプルプロジェクトをダウンロードすることができます。シミュレータ上で実行すると、次のWatchBackgroundRefresh: Using WKRefreshBackgroundTask to update WatchKit apps in the background

/* 
Copyright (C) 2016-2017 Apple Inc. All Rights Reserved. 
See LICENSE.txt for this sample’s licensing information 

Abstract: 
The main interface controller. 
*/ 

import WatchKit 
import Foundation 


class MainInterfaceController: WKInterfaceController, WKExtensionDelegate, URLSessionDownloadDelegate { 
    // MARK: Properties 

    let sampleDownloadURL = URL(string: "http://devstreaming.apple.com/videos/wwdc/2015/802mpzd3nzovlygpbg/802/802_designing_for_apple_watch.pdf?dl=1")! 

    @IBOutlet var timeDisplayLabel: WKInterfaceLabel! 

    private let dateFormatter: DateFormatter = { 
     let formatter = DateFormatter() 
     formatter.dateStyle = .none 
     formatter.timeStyle = .long 

     return formatter 
    }() 

    // MARK: WKInterfaceController 

    override func awake(withContext context: Any?) { 
     super.awake(withContext: context) 

     // Configure interface objects here. 
     WKExtension.shared().delegate = self 
     updateDateLabel() 
    } 

    // MARK: WKExtensionDelegate 
    func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) { 
     for task : WKRefreshBackgroundTask in backgroundTasks { 
      print("received background task: ", task) 
      // only handle these while running in the background 
      if (WKExtension.shared().applicationState == .background) { 
       if task is WKApplicationRefreshBackgroundTask { 
        // this task is completed below, our app will then suspend while the download session runs 
        print("application task received, start URL session") 
        scheduleURLSession() 
       } 
      } 
      else if let urlTask = task as? WKURLSessionRefreshBackgroundTask { 
       let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: urlTask.sessionIdentifier) 
       let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil) 

       print("Rejoining session ", backgroundSession) 
      } 
      // make sure to complete all tasks, even ones you don't handle 
      task.setTaskCompleted() 
     } 
    } 

    // MARK: Snapshot and UI updating 

    func scheduleSnapshot() { 
     // fire now, we're ready 
     let fireDate = Date() 
     WKExtension.shared().scheduleSnapshotRefresh(withPreferredDate: fireDate, userInfo: nil) { error in 
      if (error == nil) { 
       print("successfully scheduled snapshot. All background work completed.") 
      } 
     } 
    } 

    func updateDateLabel() { 
     let currentDate = Date() 
     timeDisplayLabel.setText(dateFormatter.string(from: currentDate)) 
    } 

    // MARK: URLSession handling 

    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { 
     print("NSURLSession finished to url: ", location) 
     updateDateLabel() 
     scheduleSnapshot() 
    } 

    func scheduleURLSession() { 
     let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: NSUUID().uuidString) 
     backgroundConfigObject.sessionSendsLaunchEvents = true 
     let backgroundSession = URLSession(configuration: backgroundConfigObject) 

     let downloadTask = backgroundSession.downloadTask(with: sampleDownloadURL) 
     downloadTask.resume() 
    } 

    // MARK: IB actions 

    @IBAction func ScheduleRefreshButtonTapped() { 
     // fire in 20 seconds 
     let fireDate = Date(timeIntervalSinceNow: 20.0) 
     // optional, any SecureCoding compliant data can be passed here 
     let userInfo = ["reason" : "background update"] as NSDictionary 

     WKExtension.shared().scheduleBackgroundRefresh(withPreferredDate: fireDate, userInfo: userInfo) { (error) in 
      if (error == nil) { 
       print("successfully scheduled background task, use the crown to send the app to the background and wait for handle:BackgroundTasks to fire.") 
      } 
     } 
    } 

} 

が出力されます。他の構成で実行されている同様の出力(必ずしも必要ではないが、全く同じ):これを見つけることが誰のために

successfully scheduled background task, use the crown to send the app to the background and wait for handle:BackgroundTasks to fire. 
received background task: <WKSnapshotRefreshBackgroundTask: 0x7b019030> 
received background task: <WKApplicationRefreshBackgroundTask: 0x7a711290> 
application task received, start URL session 
+0

いくつかの一般的なアドバイス:Swiftの命名規則を使用してください。これは関数名のためにlower-camelCaseです( 'scheduleRefreshButtonTapped()')。あなたの質問について:働いていないものとして、より多くの文脈を提供してください。スケジューリングは成功していますか? 'handle(backgroundTasks:')はこれまでに呼び出されていますか?より具体的にしてください。 –

+0

@DávidPásztorありがとうございます。私は自分のプロジェクトに動作中のAppleコードを組み込む際に、命名規則を修正しています。何がうまくいかないかの詳細については、私は質問を編集して、対応する出力のサンプルを追加しました。 – PerpetualStudent

+0

実際のiPhoneに接続された時計シミュレーターまたはiPhoneに接続された実際のApple Watchでこのコードを試しましたか? –

答えて

6

、両方URLSessionスケジューリングと私が見た2つの問題がありました。これらの変更により、私はAppleのサンプルコードが少なくともシミュレータ上で動作すると思います。

- sampleDownloadURLは安全である必要があるため、HTTPSを使用するURLが必要です。この1作品:https://api.weather.gov/points/42.3584,-71.0598/forecast

- それはURLSessionselfに設定されていなかったために、デリゲートのように私には見えますので、以下の変更は、固定その:

let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil) 

作業(以下、完全ではあるが)コードは非常に役に立ちました:What's New in watchOS 3: Background Tasks

編集:タスクが受信された直後に完了するという問題がもう1つあります。実際には、それらを(ローカル変数などに)保存し、そのタスクのすべての処理が完了した後に完了する必要があります。このコードでは、WKApplicationRefreshBackgroundTaskに掛かり、scheduleSnapshotの呼び出し直後までsetTaskCompleted()を呼び出していないことを意味すると思います。

関連する問題