ios - Watchkit 新 session 不起作用

标签 ios objective-c watchkit watchos-2

我的 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/

相关文章:

iphone - 从 objective-c 中的另一个按钮打开一个按钮

objective-c - WatchKit 的社交框架

ios - 如何在 watch 上测试不同的字体大小(动态类型)?

ios - 将应用上传到应用商店后的状态 “Missing Screenshot [1]”

ios - Segue VS didDeselectRowAtIndexPath

ios - 如何使用UIAppearance设置UIPickerView的背景颜色?

iphone - QuickDialog 的多行内联条目元素

ios - iOS 中的 self.timer = nil 与 [self.timer invalidate] 有什么区别?

swift - 如何以编程方式在 Watch 上撰写消息?

ios - 在 Apple Watch Storyboard 中的图像顶部添加标签