【问题标题】:WatchConnectivity: didReceiveApplicationContext never gets called although context is updatedWatchConnectivity:didReceiveApplicationContext 永远不会被调用,尽管上下文已更新
【发布时间】:2021-09-03 08:42:33
【问题描述】:

我遇到了以下问题:我能够在 iPhone 和 Watch(模拟器和真实设备)上启动 WCSessions,并且可以很好地使用 sendMessage 方法。我知道 updateApplicationContext 需要发送更新的字典,所以我添加了一个 uuid 用于调试目的:

context = ["user":id,"messageId": UUID().uuidString]

调用该方法时没有抛出错误,但在监视端 didReceiveApplicationContext 永远不会被调用,并且 receivedApplicationContext 字典一直保持为空。在阅读了很多类似的代码示例和文档后,我看不出我错在哪里。

我正在使用 XCode 12.5 和 iOS 14.5 以及 watchOS 7.4 构建

这是处理 WCSession 的 iOS 代码,上下文是在另一个方法中设置的,并且使用 sendMessage 成功传输 但不是 updateApplicationContext

import WatchConnectivity

public class CDVSettings : CDVPlugin, WCSessionDelegate {

var wcSession : WCSession! = nil

var didSendMessage:Bool = false

var context: [String : Any] = [:] {
    didSet {
        debugPrint("context didSet:", self.context)
        debugPrint("WCSession.isPaired: \(wcSession.isPaired), WCSession.isWatchAppInstalled: \(wcSession.isWatchAppInstalled)")
        if wcSession.activationState == WCSessionActivationState.activated {
            do {
                debugPrint("updateApplicationContext is called")
                self.didSendMessage=true
                try wcSession.updateApplicationContext(self.context)
            }
            catch let error as NSError {
                debugPrint(error.localizedDescription)
            }
            catch {}
            wcSession.sendMessage(self.context, replyHandler: { reply in
                print("Got reply: \(reply)")
            }, errorHandler: { error in
                print("error: \(error)")
            })
        } else {
            print("activationState is not activated")
            wcSession.activate()
        }
    }
}

public func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
    print("activationDidCompleteWith activationState:\(activationState) error:\(String(describing: error))")
}

public func sessionDidBecomeInactive(_ session: WCSession) {
    
}

public func sessionDidDeactivate(_ session: WCSession) {

}

@objc(pluginInitialize)
public override func pluginInitialize() {
    wcSession = WCSession.default
    wcSession.delegate = self
    wcSession.activate()
}

[...]

}

这是手表部分:

    import WatchConnectivity
    
    class ConnectivityRequestHandler: NSObject, ObservableObject, WCSessionDelegate {
    
    var session = WCSession.default

    override init() {
        super.init()
        session.delegate = self
        session.activate()
        debugPrint("ConnectivityRequestHandler started with session", session)
    }
        
    // MARK: WCSession Methods
    
    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        debugPrint(error)
        debugPrint("session is reachable:",session.isReachable)
        debugPrint("last received application context:",session.receivedApplicationContext)
    }
    
    
   func session(_ session: WCSession, didReceiveMessage message: [String: Any], replyHandler: @escaping ([String: Any]) -> Void) {
        debugPrint("didReceiveMessage: \(message)")
        replyHandler(["message received": Date()])
    }
    
    func session(_ session: WCSession, didReceiveMessageData messageData: Data, replyHandler: @escaping (Data) -> Void) {
        debugPrint("didReceiveMessageData: \(messageData)")
    }
    
    func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
        debugPrint("did receive application context")
        debugPrint(applicationContext)
            if let id = applicationContext["user"] as? [String]{
                debugPrint("\(id)")
                UserDefaults.standard.set(id, forKey: "user")
            }
        }

}

iOS上对应的日志

"context didSet:" ["user": "0e4a28b5-f8a0-40a5-942d-5f13b610a93a", "messageId": "8A78246C-91E6-48DC-B55D-4F4EBC761211"] “WCSession.isPaired:真,WCSession.isWatchAppInstalled:真” “调用updateApplicationContext”得到回复:[“收到消息”: 2021-09-03 08:31:54 +0000]

在 watchOS 上

"ConnectivityRequestHandler 以会话开始" nil "session is 可达:" true "最后收到的应用程序上下文:" [:] “didReceiveMessage:[“用户”:0e4a28b5-f8a0-40a5-942d-5f13b610a93a, "messageId": 8A78246C-91E6-48DC-B55D-4F4EBC761211]"

我做错了什么?非常感谢您的帮助。

【问题讨论】:

  • 您在哪里 print("activationDidCompleteWith ... 如果会话激活成功完成,您不想调用更新应用上下文吗?
  • @Shadowrun 上下文更新发生在 CDVPlugin 生命周期的后期,但由于消息仅在 WCSessionActivationState.activated 为(仍然)为真之后发送,这不应该是问题的根源,我猜……
  • 您是在模拟器上还是在物理设备上观察它?过去我确实遇到过类似的模拟器问题。在我的情况下,我能够传输应用程序上下文,但 transferUserInfo 从未工作过:stackoverflow.com/questions/65530895/… 但是,在真实设备上,相同的代码按预期工作。我找不到模拟器的解决方案。
  • @VadimBelyaev 重新启动物理设备后,代码按预期工作!非常感谢您指出这一点,我在研究时阅读了您的问题,但显然过于关注模拟人生。无论如何,WatchConnectivity 模拟器的工作方式似乎是随机的,这真的很奇怪。

标签: ios swift watchkit watchos watchconnectivity


【解决方案1】:

对于那些在研究时遇到我的问题的人来说,这不是真正的解决方案,而是我(现在)与他人分享的一个观察结果(参见上面的 cmets):使用 real devices工作 符合预期,但您可能需要在此过程中重新启动它们。在模拟器中,似乎不同的方法可能有效,而其他方法则无效,甚至因开发人员而异。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-27
    • 2013-10-12
    • 2012-03-27
    • 2013-08-29
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    相关资源
    最近更新 更多