我的 watch 扩展中有两个 View Controller 。每当我调用
[[WCSession defaultSession] sendMessage:applicationData replyHandler:^(NSDictionary *reply) {}
我只得到第一个 View Controller 的响应,第二个 View Controller 出现错误
Error Domain=WCErrorDomain Code=7011 "Message reply failed."
UserInfo={NSUnderlyingError=0x79f1f100 {Error Domain=WCErrorDomain Code=7010 "Payload contains unsupported type."
UserInfo={NSLocalizedRecoverySuggestion=Only pass valid types., NSLocalizedDescription=Payload contains unsupported type.}}, NSLocalizedDescription=Message reply failed.}
WCSession 在应用程序和 watch 扩展中启动。有什么建议吗?
最佳答案
在WCSessionDelegate's - session:didReceiveMessage:replyHandler:
方法中,replyHandler
参数定义为 [String : AnyObject]
。 AnyObject
部分具有误导性。它只能包含 property list数据类型:NSData
, NSString
, NSArray
, NSDictionary
, NSDate
, and NSNumber
. (在这种情况下,选择 AnyObject
是有道理的,因为除了 NSObject
之外,这 6 种数据类型没有继承自公共(public)子类。)
通常人们会提到 NSCoding and NSKeyedArchiver可以解决这个问题,但除此之外我没有看到更多的例子/解释。
需要注意的是replyHandler
字典不关心序列化。您可以使用 NSKeyedArchiver、JSON、您自己的自定义编码等。只要字典只包含这 6 种数据类型,replyHandler 就会很高兴。否则,您会看到 Payload contains unsupported type.
错误。
因此,您永远不能像这样调用回复处理程序:replyHandler(["response": myCustomObject)
,即使 myCustomObject
实现了 NSCoding
协议(protocol)完美。
编码选择总结:
- NSCoding:主要优点是当您取消存档时,它会自动找到正确的类并为您实例化它,包括其子图中的任何对象。
- JSON
- 自定义编码:一个优点是您的对象不会强制继承自 NSObject,这有时在 Swift 中很有用。
如果你确实使用了 NSCoding,这就是它的样子:
iPhone 应用程序:
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
let data = NSKeyedArchiver.archivedDataWithRootObject(myCustomObject)
replyHandler(["response": data])
}
watch 应用:
WCSession.defaultSession().sendMessage([],
replyHandler: {
response -> Void in
let myCustomObject = NSKeyedUnarchiver.unarchiveObjectWithData(response["response"])
}, errorHandler: nil
)
请注意,如果您想在取消归档对象时从崩溃中恢复,您将需要使用新的 iOS 9 API,unarchiveTopLevelObjectWithData , 如果有问题,它会抛出一个错误。
注意:您的自定义对象必须继承自NSObject
,否则在归档时会出现以下错误:
*** NSForwarding: warning: object ... of class 'Foo' does not implement methodSignatureForSelector: -- trouble ahead Unrecognized selector -[Foo replacementObjectForKeyedArchiver:]
关于ios - Watchkit 新 session 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32970099/