WCSession
方法sendMessage:replyHandler:errorHandler:
与iOS应用程序通信。
iOS应用程序正确回复,但有时我会收到域代码为WCErrorDomain
,代码为7014
的错误:“无法传递有效负载”
当iOS应用程序不在前景时,这种情况发生得更频繁。
我找不到任何解决此问题的方法,希望你们中的某个人知道如何解决此问题。
WCSession
方法sendMessage:replyHandler:errorHandler:
与iOS应用程序通信。
iOS应用程序正确回复,但有时我会收到域代码为WCErrorDomain
,代码为7014
的错误:“无法传递有效负载”
当iOS应用程序不在前景时,这种情况发生得更频繁。
我找不到任何解决此问题的方法,希望你们中的某个人知道如何解决此问题。
在我的情况下,我需要实现两个委托:
一个没有任何replyHandler
的
func session(_ session: WCSession,
didReceiveMessage message: [String : Any])
带有 replyHandler 的那个 元素
func session(_ session: WCSession,
didReceiveMessage message: [String : Any],
replyHandler: @escaping ([String : Any]) -> Void)
如果您发送一个没有 replyHandler
的消息,则会运行第一个委托。
如果您发送一个带有 replyHandler
的消息,则会运行第二个委托。
在某些情况下,我只发送消息,在其他情况下,我发送消息并期望对方回复。
但是... 我只实现了第二个委托 -_-
无论如何,最终为了减少重复代码,我实现了一个通用的方法,最终得到了:
func session(_ session: WCSession,
didReceiveMessage message: [String : Any]) {
handleSession(session,
didReceiveMessage: message)
}
func session(_ session: WCSession,
didReceiveMessage message: [String : Any],
replyHandler: @escaping ([String : Any]) -> Void) {
handleSession(session,
didReceiveMessage: message,
replyHandler: replyHandler)
}
//Helper Method
func handleSession(_ session: WCSession,
didReceiveMessage message: [String : Any],
replyHandler: (([String : Any]) -> Void)? = nil) {
//Common logic
}
观察OS 4
如果你在使用Swift3的iOS10 beta 6和GM版本时遇到了问题,解决方法是修改iOS应用程序中的委托函数头如下:
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
请注意 @escaping 和 Any 类型而不是 AnyObject 类型。
-(void)sendDataToPhone:(NSDictionary* _Nonnull)dictData
{
if(WCSession.isSupported){
WCSession* session = WCSession.defaultSession;
session.delegate = self;
[session activateSession];
if(session.reachable)
{
[session sendMessage:dictData replyHandler: ^(NSDictionary<NSString *,id> * __nonnull replyMessage) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@".....replyHandler called --- %@",replyMessage);
// Play a sound in watch
[[WKInterfaceDevice currentDevice] playHaptic:WKHapticTypeSuccess];
});
}
errorHandler:^(NSError * __nonnull error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Error = %@",error.localizedDescription);
});
}
];
}
else
NSLog(@"Session Not reachable");
}
else
NSLog(@"Session Not Supported");
}
#pragma mark - Standard WatchKit delegate
-(void)sessionWatchStateDidChange:(nonnull WCSession *)session
{
if(WCSession.isSupported){
WCSession* session = WCSession.defaultSession;
session.delegate = self;
[session activateSession];
}
}
// Allocating WCSession inorder to communicate back to watch.
if(WCSession.isSupported){
WCSession* session = WCSession.defaultSession;
session.delegate = self;
[session activateSession];
}
#pragma mark - WCSession Delegate
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *, id> *)message replyHandler:(void(^)(NSDictionary<NSString *, id> *replyMessage))replyHandler
{
if(message){
NSData *receivedData = [message objectForKey:@"AudioData"];
NSDictionary* response = @{@"response" : [NSString stringWithFormat:@"Data length: %lu",(unsigned long)receivedData.length]} ;
replyHandler(response);
}
}
#pragma mark - Standard WatchKit Delegate
-(void)sessionWatchStateDidChange:(nonnull WCSession *)session
{
if(WCSession.isSupported){
WCSession* session = WCSession.defaultSession;
session.delegate = self;
[session activateSession];
if(session.reachable){
NSLog(@"session.reachable");
}
if(session.paired){
if(session.isWatchAppInstalled){
if(session.watchDirectoryURL != nil){
}
}
}
}
}
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
//code
replyHandler (answer as [String : Any])
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
SessionHandler()
}
更改如下以使其正常工作:
",保留HTML标记,不做解释。var handler: SessionHandler!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
handler = SessionHandler()
}
正在开发一个应用程序,遇到了完全相同的问题。
我相当确定已经在我的代码中到处查找并没有发现任何错误。我最好的猜测是这一定是 WatchConnectivity
的一个 bug。
我的当前错误处理程序解决方法只是尝试在出现此特定错误时重新加载数据。不是很美观,但它可以正常工作。
你可能想尝试类似的解决方案?
func messageErrorHandler(error: NSError) {
isLoading = false
print("Error Code: \(error.code)\n\(error.localizedDescription)")
// TODO: WTF?. Check future releases for fix on error 7014, and remove this...
if error.code == 7014 {
// Retry after 1.5 seconds...
retryTimer = NSTimer.scheduledTimerWithTimeInterval(
NSTimeInterval(1.5), target: self, selector: "reloadData", userInfo: nil, repeats: false)
return
}
displayError("\(error.localizedDescription) (\(error.code))",
message: "\(error.localizedDescription)")
}
更新:
对于任何使用WatchConnectivity
的人; 我需要一个类似的“hack”来测试session.reachable
变量。
我注意到我的应用程序在会话变得可达之前就成功发送了一条消息。因此,我只需在实际告诉用户他们的手机无法连接之前尝试重新加载数据(重新发送消息)几次即可。
更新2:
上面的示例使用了.sessionWatchStateDidChange()
,因此问题不是由于没有等待连接确认而导致.sendMessage()
触发太早。这一定是一个错误,因为它并不是每次都发生,只是在100条消息中出现1次。
WCSession
代理实现以下方法。由于缺少实现,我遇到了这个错误。- (void)session:(WCSession * _Nonnull)session
didReceiveMessage:(NSDictionary<NSString *, id> * _Nonnull)replyMessage
replyHandler:(void (^ _Nonnull)(NSDictionary<NSString *, id> * _Nonnull replyMessage))replyHandler
{
NSLog(@"Received. %@", replyMessage);
[self processResponse:replyMessage];
}
didReceiveMessage
方法来解决问题:func session(_ session: WCSession, didReceiveMessage message: [String : Any],
replyHandler: @escaping ([String : Any]) -> Void)
检查委托是否连接正确?
WCSession* session = WCSession.defaultSession;
session.delegate = self;
[session activateSession];
session.delegate = self;
是否设置为 self。
error.userInfo[NSUnderlyingErrorKey]
)?看到发送消息的代码和应该接收它的委托方法的实现会很好! - ccjensen