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.
您的流程是正确的,但难点在于了解如何调试:
调试观察:
- 运行 iPhone 目标,完成后点击停止按钮。
- 在模拟器中打开 iOS 应用程序(运行 从模拟器手动打开它,而不是从 Xcode)并让它挂在那里。
- 切换到 Watch 目标(yourAppName WatchKit App),放置相关断点并 运行 它。
- 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 的回答有一个重要的考虑因素。
最近在做一个项目又跟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.
您的流程是正确的,但难点在于了解如何调试:
调试观察:
- 运行 iPhone 目标,完成后点击停止按钮。
- 在模拟器中打开 iOS 应用程序(运行 从模拟器手动打开它,而不是从 Xcode)并让它挂在那里。
- 切换到 Watch 目标(yourAppName WatchKit App),放置相关断点并 运行 它。
- 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 的回答有一个重要的考虑因素。