Watchkit-didReceiveApplicationContext仅在第一次工作

时间:2018-06-26 13:33:57

标签: ios swift3 watchconnectivity wcsession

当我在Xcode中使用iOS和watchOS模拟器运行Watch Connectivity应用程序时,WCSession委托方法 didReceiveApplicationContext 只能首次使用,但是不会被调用,并且Interface控制器中没有任何更改。谁能解释为什么会这样吗?

下面是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)
        }
    }
}

下面是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)
    }
}

1 个答案:

答案 0 :(得分:2)

其原因是因为updateApplicationContext仅在应用程序上下文字典的内容更改时触发。 apple documentation将其描述为(强调是我的):

  

使用updateApplicationContext(_ :)方法将最新状态信息传达给对方。当对方唤醒时,它可以使用此信息来更新其自身的状态。例如,支持后台应用刷新的iOS应用可以使用其后台执行时间的一部分来更新相应的Watch应用。 此方法会覆盖以前的数据字典,因此当您的应用仅需要最新的数据值时使用此方法

因此,可以将其视为属性设置器方法,该方法仅在值实际更改时才触发KVO。这里,接收方委托方法仅在字典的内容更改时才触发,因此在上面的示例中,如果您更改此行:

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

要这样:

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

您会看到接收方委托每次都会得到一个回调。