【问题标题】:Watchkit - didReceiveApplicationContext works only for the first timeWatchkit - didReceiveApplicationContext 仅在第一次工作
【发布时间】:2018-06-26 13:33:56
【问题描述】:

当我在 Xcode 中使用 iOS 和 watchOS 模拟器运行手表连接应用程序时,WCSession 委托方法 didReceiveApplicationContext 仅在第一次工作,但随后没有被调用,并且接口控制器中没有任何变化。谁能解释一下为什么会这样?

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

【问题讨论】:

    标签: ios swift3 watchconnectivity wcsession


    【解决方案1】:

    之所以会这样,是因为updateApplicationContext只有在应用上下文字典的内容发生变化时才会触发。 apple documentation 将其描述为(重点是我的):

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

    所以把它想象成一个属性设置方法,只在值实际发生变化时才触发 KVO。这里接收方委托方法仅在字典内容更改时触发,因此在上面的示例中,如果您更改此行:

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

    变成这样:

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

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

    【讨论】:

    • 谢谢@ccjensen,我从早上开始就一直在努力解决这个问题。明白了这个问题。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2016-02-17
    • 2017-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    相关资源
    最近更新 更多