Watchkit新会话不起作用

YaB*_*eep 6 objective-c ios watchkit watchos-2

我的手表扩展中有两个视图控制器.每当我打电话时

[[WCSession defaultSession] sendMessage:applicationData replyHandler:^(NSDictionary *reply)  {}
Run Code Online (Sandbox Code Playgroud)

我只得到第一个视图控制器的响应,并在第二个viewcontroller中得到错误

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.}
Run Code Online (Sandbox Code Playgroud)

WCSession在app和watch扩展中启动.任何建议?

Sen*_*ful 12

WCSessionDelegate的 - session:didReceiveMessage:replyHandler:方法中,replyHandler参数定义为[String : AnyObject].这AnyObject部分具有误导性.它只能包含一个属性列表数据类型:NSData,NSString,NSArray,NSDictionary,NSDate,和NSNumber.(在这种情况下,AnyObject选择的原因是有道理的,因为这6种数据类型不会从公共子类继承NSObject.)

通常有人提到NSCoding和NSKeyedArchiver可以解决这个问题,但除此之外我还没有看到更多的例子/解释.

需要注意的是,replyHandler字典并不关心序列化.您可以使用NSKeyedArchiver,JSON,您自己的自定义编码等.只要字典只包含那6种数据类型,replyHandler就会很高兴.否则你会看到Payload contains unsupported type.错误.

因此,您永远不能像这样调用回复处理程序:replyHandler(["response": myCustomObject),即使完美地myCustomObject实现了NSCoding协议.

编码选择摘要:

  • NSCoding:主要优点是当你取消归档时,它会自动找到正确的类并为你实例化它,包括其子图中的任何对象.
  • JSON
  • 自定义编码:一个优点是您的对象不会被强制从NSObject继承,这在Swift中有时很有用.

如果您使用NSCoding,这就是它的样子:

iPhone App:

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    let data = NSKeyedArchiver.archivedDataWithRootObject(myCustomObject)
    replyHandler(["response": data])
}
Run Code Online (Sandbox Code Playgroud)

观看应用:

WCSession.defaultSession().sendMessage([],
    replyHandler: {
        response -> Void in
        let myCustomObject = NSKeyedUnarchiver.unarchiveObjectWithData(response["response"])
    }, errorHandler: nil
)
Run Code Online (Sandbox Code Playgroud)

请注意,如果要在取消归档对象时从崩溃中恢复,则需要使用新的iOS 9 API,unarchiveTopLevelObjectWithData,如果出现问题则会抛出错误.

注意:您的自定义对象必须继承NSObject,否则归档时会出现以下错误:

***NSForwarding:警告:类'Foo'的对象...没有实现methodSignatureForSelector: - 提前麻烦无法识别的选择器 - [Foo replacementObjectForKeyedArchiver:]


leh*_*058 7

"Payload包含不受支持的类型"可能意味着您在消息字典中发送自定义对象.您需要序列化此数据以仅包含受支持的类型(NSNumber,NSDate,NSString,NSData,NSArray和NSDictionary).

我有一个github项目,可以自动将您的自定义对象序列化为安全的对象以进行watchkit传输.你可以在这里查看.


YaB*_*eep 1

我通过将字典格式的 JSON 字符串直接发送到 iPhone 应用程序 Appdelegate 的回调方法来解决这个问题

- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *, id> *)message replyHandler:(void(^)(NSDictionary<NSString *, id> *replyMessage))replyHandler {
Run Code Online (Sandbox Code Playgroud)

而不是将 JSON 字典转换为普通字典。并在 watch viewcontroller 回调方法中将此 JSON 字典转换为普通字典

[[WCSession defaultSession] sendMessage:applicationData
                           replyHandler:^(NSDictionary *reply) {}
Run Code Online (Sandbox Code Playgroud)

由于我从手表中的两个不同的视图控制器调用此方法,因此第一次从 iPhone 应用程序发送普通字典到手表工作正常,但由于某些原因,如果我从 iPhone 应用程序发送字典到手表,我会收到问题中的错误对于手表的第二个视图控制器。