简体   繁体   English

Watchkit-didReceiveApplicationContext仅在第一次工作

[英]Watchkit - didReceiveApplicationContext works only for the first time

When I run an watch connectivity app with iOS and watchOS simulators in Xcode, WCSession delegate method didReceiveApplicationContext works only for the first time, but then it is not called and nothing changes in the Interface controller. 当我运行在Xcode,WCSession委托方法didReceiveApplicationContext只在第一次的作品,但后来它不叫,没有什么在接口控制器改变iOS和watchOS模拟器的手表连接的应用程序。 Can anyone please explain the reason why is this happening? 谁能解释为什么会这样吗?

Below is WCSessionVC class of UIViewController 下面是UIViewController的WCSessionVC类

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)
        }
    }
}

Below is InterfaceController class of WKInterfaceController 下面是WKInterfaceController的InterfaceController类

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)
    }
}

The reason for this is because updateApplicationContext only triggers when the contents of the application context dictionary changes. 这是因为updateApplicationContext仅在应用程序上下文字典的内容更改时触发。 The apple documentation describes it as (emphasis is mine): 苹果文档将其描述为(重点是我的):

Use the updateApplicationContext(_:) method to communicate recent state information to the counterpart. 使用updateApplicationContext(_ :)方法将最新状态信息传达给对方。 When the counterpart wakes, it can use this information to update its own state. 当对方唤醒时,它可以使用此信息来更新其自身的状态。 For example, an iOS app that supports Background App Refresh can use part of its background execution time to update the corresponding Watch app. 例如,支持后台应用刷新的iOS应用可以使用其后台执行时间的一部分来更新相应的Watch应用。 This method overwrites the previous data dictionary, so use this method when your app needs only the most recent data values . 此方法将覆盖以前的数据字典,因此当您的应用仅需要最新的数据值时,请使用此方法

So think of it as a property setter method that only triggers KVO when the value actually changes. 因此,可以将其视为仅在值实际更改时才触发KVO的属性设置器方法。 Here the receiving side delegate method is only triggered when the contents of the dictionary changes, so in your example above if you change this line: 这里,仅当字典的内容更改时才触发接收方委托方法,因此在上面的示例中,如果您更改此行:

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

to be this: 是这样的:

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

You'll see the receiving side delegate gets a callback each time. 您会看到接收方委托每次都得到一个回调。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM