WCSession.sendMessage 作品 50/50

WCSession.sendMessage works 50/50

最近在做一个项目又跟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(手势: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.

进行单方面调试

有时会打印出“receives gesture”,有时不会。收到通知也是一样。

我猜你对 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)")

我不知道在 WCSession 中传输时 Int 是否会环绕到 NSNumber。如果是,那一定是为什么当我使用 Int 作为枚举的基数 class 时它不起作用,而当 String 是基数 class.

时它起作用

Connectivity Known Issue Your app may crash when using NSNumber and NSDate objects with the WCSession API.

Workaround: Convert an NSNumber or NSDate object to a string before calling WCSession APIs. Do the opposite conversion on the receiving side.

Watch OS 2 Beta 4 release note

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

调试观察:

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

与 debug watch 完全相反

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