【问题标题】:WCSession.sendMessage works 50/50WCSession.sendMessage 工作 50/50
【发布时间】:2015-07-08 03:04:20
【问题描述】:

最近,我又在做一个与Watch/iPhone通讯有关的项目。但是我的代码有时可以工作,有时不能工作,这对我来说有点奇怪,因为我认为代码要么工作要么不工作。它不能是 50/50。因此,我不知道出了什么问题。

在 iPhone 上设置 WCSession:

class WatchCommunicationController: NSObject, WCSessionDelegate {

    var session : WCSession?

    override init(){

        //  super class init
        super.init()

        //  if WCSession is supported
        if WCSession.isSupported() {    //  it is supported

            //  get default session
            session = WCSession.defaultSession()

            //  set delegate
            session!.delegate = self

            //  activate session
            session!.activateSession()

        } else {

            print("iPhone does not support WCSession")
        }
    }

    ... ...
}

Watch 上的类似 WCSession 设置:

class PhoneCommunicationController: NSObject, WCSessionDelegate {

    var session : WCSession?

    override init(){

        //  super class init
        super.init()

        //  if WCSession is supported
        if WCSession.isSupported() {    //  it is supported

            //  get default session
            session = WCSession.defaultSession()

            //  set delegate
            session!.delegate = self

            //  activate session
            session!.activateSession()
        } else {

            print("Watch does not support WCSession")
        }
    }

    ... ...
}

在 Watch 上发送消息:

func sendGesture(gesture : GKGesture){

//  if WCSession is reachable
if session!.reachable {     //  it is reachable

    //  create the interactive message with gesture
    let message : [String : AnyObject]
    message = [
                "Type":"Gesture",
                "Content":gesture.rawValue
              ]

    //  send message
    session!.sendMessage(message, replyHandler: nil, errorHandler: nil)
    print("Watch send gesture \(gesture)")

} else{                     //  it is not reachable

    print("WCSession is not reachable")
}

}

相关枚举:

enum GKGesture: Int {
    case Push = 0, Left, Right, Up, Down
}

在 iPhone 上接收消息:

func session(session: WCSession, didReceiveMessage message: [String : AnyObject]) {

        //retrieve info
        let type = message["Type"] as! String
        let content = message["Content"]

        switch type {

        case "Gesture":
            handleGesture(GKGesture(rawValue: content as! Int)!)
        default:
            print("Received message \(message) is invalid with type of \(type)")
        }

    }

    func handleGesture(gesture : GKGesture){

        print("iPhone receives gesture \(gesture)")

        var notificationName = ""

        switch gesture {

        case .Up:
            notificationName = "GestureUp"
        case .Down:
            notificationName = "GestureDown"
        case .Left:
            notificationName = "GestureLeft"
        case .Right:
            notificationName = "GestureRight"
        case .Push:
            notificationName = "GesturePush"
        }

        NSNotificationCenter.defaultCenter().postNotificationName(notificationName, object: nil)

    }

不知何故,我无法在 Xcode 上调试我的 Watch 应用程序,调试会话无法附加。我不知道为什么。因此,我只用 iPhone 进行单面调试。

有时我会打印出“接收手势”,有时不会。获取通知也是如此。

【问题讨论】:

  • 您是否尝试过“重置内容和设置”并重新启动手表/iPhone 模拟器和 Xcode?这是附加调试会话的提示。告诉我情况如何,然后我可以尝试帮助您解决 WatchConnectivity 问题
  • 我用我的 iPhone 和 Apple Watch 进行调试。
  • 您是否需要为可访问性做一些特别的事情?我的代码几乎完全相同,但在检查可达性时,我的检查总是返回 false
  • 我不这么认为。我认为只要 iPhone 连接 wifi,打开蓝牙,并与 Apple Watch 配对。它们应该是可访问的。

标签: ios swift watchos-2


【解决方案1】:

我不知道 Int 在 WCSession 中传输时是否会被包裹到 NSNumber。如果是这样,那么这就是为什么当我使用 Int 作为枚举的基类时它不起作用并且当 String 是基类时起作用。

连接已知问题 使用 NSNumber 和 使用 WCSession API 的 NSDate 对象。

解决方法:将 NSNumber 或 NSDate 对象转换为字符串之前 调用 WCSession API。在接收上做相反的转换 一边。

Watch OS 2 Beta 4 release note

【讨论】:

    【解决方案2】:

    我的猜测是您对 sendMessage 的调用在失败的情况下会返回错误,但您还没有实现错误处理程序!现在,当你启动并运行时,你可以只打印错误,但如果这是运输代码,你真的应该处理适当的错误:

    //  send message
    session.sendMessage(message, replyHandler: nil, errorHandler: { (error) -> Void in
        print("Watch send gesture \(gesture) failed with error \(error)")
    })
    print("Watch send gesture \(gesture)")
    

    【讨论】:

    • 我通过将枚举从 Int 更改为 String 来修复它。我现在每次都工作。你能想到为什么吗?更多信息:通过更改我按手表上的按钮触发此发送消息的每件事,它会在状态栏上显示微小的进度指示器。但改变后不再。
    • 不,这对我来说没有任何意义 :) 我可能需要查看实际代码并自己运行它才能为您获得更多答案
    【解决方案3】:

    您的流程是正确的,但难点在于理解如何调试:

    调试观察:

    1. 运行 iPhone 目标,完成后点击停止按钮。
    2. 在模拟器中打开 iOS 应用(从模拟器中手动运行,而不是从 Xcode 中运行)并让它挂在那里。
    3. 切换到Watch目标(yourAppName WatchKit App),放置相关断点并运行。
    4. iOS 应用程序将自动置于后台,然后您将能够使用 sendMessage 方法(在 Watch 目标处)发送您需要的任何内容,如果您的 iOS 应用程序中有 replayHandler,您甚至会收到相关的Watch 目标(即 InterfaceController)的 sendMessage 内的消息

    小 Swift 示例:

    将字典从 Watch 发送到 iOS 应用:

        if WCSession.defaultSession().reachable == true {
            let requestValues = ["Send" : "From iWatch to iPhone"]
            let session = WCSession.defaultSession()
    
            session.sendMessage(requestValues,
                replyHandler: { (replayDic: [String : AnyObject]) -> Void in
                    print(replayDic["Send"])
    
                }, errorHandler: { (error: NSError) -> Void in
                    print(error.description)
            })
        }
        else
        {
            print("WCSession isn't reachable from iWatch to iPhone")
        }
    

    从 Watch 接收消息并从 iOS 应用发送重播:

        func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    
          print(message.values)
    
          var replyValues = Dictionary<String, AnyObject>()
    
          replyValues["Send"] = "Received from iphone"
          // Using the block to send back a message to the Watch
          replyHandler(replyValues)
         }
    

    调试 iPhone:

    与调试手表完全相反

    另外,@sharpBaga 的回答有一个重要的考虑因素。

    【讨论】:

      猜你喜欢
      • 2018-02-21
      • 2015-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多