Watchkit - didReceiveApplicationContext работает только в первый раз - PullRequest
0 голосов
/ 26 июня 2018

Когда я запускаю приложение для подключения часов с iOS и имитаторами watchOS в XCode, метод делегата WCSession didReceiveApplicationContext работает только в первый раз, но затем он не вызывается и ничего не изменяется в контроллере интерфейса. Может кто-нибудь объяснить, почему это происходит?

Ниже представлен класс WCSessionVC UIViewController

import Foundation
import UIKit
import WatchConnectivity

class WCSessionVC: UIViewController, WCSessionDelegate {

    let session = WCSession.default

    override func viewDidLoad() {
        super.viewDidLoad()

        session.delegate = self
        session.activate()
    }

    func updateApplicationContext(applicationContext: [String : Any]) throws {
        if WCSession.default.isPaired {
            do {
                try WCSession.default.updateApplicationContext(applicationContext)
            } catch let error {
                throw error
            }
        }
    }

    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        print("Session activated")
        let message = ["quote": "Hello"]
        do {
            try self.updateApplicationContext(applicationContext: message as [String : Any])
        }
        catch {
            print(error)
        }
    }
}

Ниже приведен класс InterfaceController для WKInterfaceController

import WatchKit
import Foundation
import WatchConnectivity

class InterfaceController: WKInterfaceController, WCSessionDelegate {

    @IBOutlet var lblUserId: WKInterfaceLabel!

    var watchSession: WCSession? {
        didSet {
            if let session = watchSession {
                session.delegate = self
                session.activate()
            }
        }
    }

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

        if let session = watchSession {
            session.delegate = self
            session.activate()
        }
        // Configure interface objects here.
    }

    override func willActivate() {
        // This method is called when watch view controller is about to be visible to user
        super.willActivate()
        //loadDataFromDatastore()
        watchSession = WCSession.default
    }

    override func didDeactivate() {
        // This method is called when watch view controller is no longer visible
        super.didDeactivate()
    }

    //MARK: Delegate Methods
    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        watchSession?.activate()
        print("Session activation did complete")
    }

    func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
        DispatchQueue.main.async {
            print("watch received app context: ", applicationContext)
            if let data = applicationContext["quote"] as? String {
                self.lblUserId.setText(data)
            }
        }
    }

    func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
        print(message)
    }
}

1 Ответ

0 голосов
/ 30 июня 2018

Причина этого в том, что updateApplicationContext срабатывает только при изменении содержимого словаря контекста приложения. яблочная документация описывает это как (выделение мое):

Используйте метод updateApplicationContext (_ :) для передачи последней информации о состоянии коллеге. Когда коллега просыпается, он может использовать эту информацию для обновления своего собственного состояния. Например, приложение iOS, которое поддерживает фоновое обновление приложения, может использовать часть своего времени выполнения в фоновом режиме для обновления соответствующего приложения Watch. Этот метод перезаписывает предыдущий словарь данных, поэтому используйте этот метод, когда вашему приложению нужны только самые последние значения данных .

Так что думайте о нем как о методе установки свойств, который запускает KVO только тогда, когда значение действительно изменяется. Здесь метод делегата принимающей стороны запускается только при изменении содержимого словаря, поэтому в приведенном выше примере вы измените эту строку:

let message = ["quote": "Hello"]

быть таким:

let message = ["quote": "Hello", "date": NSDate()]

Вы увидите, что делегат принимающей стороны получает обратный вызов каждый раз.

...