WCSession sendMessage:replyHandler错误代码7014(WCErrorCodeDeliveryFailed)
我有一个Watch OS 2应用程序,通过WCSession
方法sendMessage:replyHandler:errorHandler:
与iOS应用程序进行通信sendMessage:replyHandler:errorHandler:
iOS应用程序正确回复,但我得到错误与域WCErrorDomain
代码7014
:“有效载荷无法传递”
当iOS应用程序不是前台时更经常发生这种情况。
我没有find任何解决这个问题的办法,我希望你们中的一个知道解决这个问题的方法
对于在iOS10 beta6和GM上遇到问题的人,您正在使用Swift3,解决scheme是将iOS应用程序中的委托function标题更改为以下内容:
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
注意@escaping和Any而不是AnyObjecttypes。
试试这一个,这解决了我的问题。 在InterfaceController里添加下面的方法将数据传递给手机。
-(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]; } }
在手机端,添加以下代码以接收来自手表的数据。
在didFinishLaunchingWithOptions中添加以下内容。
// Allocating WCSession inorder to communicate back to watch. if(WCSession.isSupported){ WCSession* session = WCSession.defaultSession; session.delegate = self; [session activateSession]; }
现在添加WCSessionDelegate。
#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){ } } } } }
希望这可以帮助你:)
对不起,我没有足够的声望评论答案。 我的问题得到解决与彼得罗伯特的答案:使用Swift 3 WCErrorCodeDeliveryFailed出现,解决scheme是简单地将AnyObject更改为任何replyHandlers。
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) { //code replyHandler (answer as [String : Any]) }
稍后在应用程序生命周期中遇到同样的移动WCSession初始化(设置委派并激活它)解决了问题。
我在应用代理didFinishLaunching中激活了WCSession,并在那里破坏了通信。 稍后在应用程序中移动WCSession初始化使通信再次工作。
您可能需要(检查并)实现您的WCSession
委托实现以下方法。 由于缺less实现,我得到了这个错误。
- (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]; }
检查代理连接是否正确?
WCSession* session = WCSession.defaultSession; session.delegate = self; [session activateSession];
注意:validationsession.delegate = self;
设置为自己。
在应用程序上工作,并具有完全相同的行为。 我相当肯定,我已经在我的代码无处不在,发现没有错。 我最好的猜测是,这一定是WatchConnectivity
一个bug。
我当前的error handling程序解决方法只是试图重新加载数据上这个特定的错误。 不是很漂亮,但它工作正常。
你可能想尝试类似的东西?
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
人WatchConnectivity
, 我需要有一个类似的“黑客”来testingsession.reachable
variables。
我注意到,我的应用程序设法发送一个消息之前,会话成为可及。 所以我只是尝试重新加载数据(重新发送消息)几次,然后才实际告诉用户他们的电话是遥不可及的。
更新2:上面的示例使用.sessionWatchStateDidChange()
,所以问题不是.sendMessage()
由于不等待连接确认触发得太早。 这肯定是一个错误,因为它不是每次都发生,它只是每100条消息就有1个。
我发现把答复代码作为第一件事情来解决这个问题(可能是由于超时造成的)。
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: ([String : Any]) -> Void) { print("Message - received") //Send reply let data = ["receivedData" : true] replyHandler(data as [String : AnyObject]) }
在Swift 3中,我解决了使用此签名实现didReceiveMessage
:
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void)
确保您的会话始终处于活动状态。 例如,我有一个其他的视图,这是testing的一部分,然后返回到最初的视图,并想知道为什么会话不活跃了。
- (void)willActivate { // This method is called when watch view controller is about to be visible to user [super willActivate]; //Setup WCSession if ([WCSession isSupported]) { [[WCSession defaultSession] setDelegate:self]; [[WCSession defaultSession] activateSession]; }}
以上为我做了。 如果它第一次置于awakeWithContext,愚蠢的我….
这个场景将涵盖几个用例。 请看看这些步骤,这对我很有帮助。
1 – 了解每个设备必须configuration自己的WCSession实例,并configuration相应的代理。
2 – 仅在每个设备上的一个地方实现WCSessionDelegate,ej。 在AppDelegate上的iOS应用上,在ExtensionDelegate上的watchOS上。 这是非常重要的,因为在watchOS上configuration适当的WCSession,但是在iPhone上实现两个不同的地方,ej。 在应用程序委托,然后在应用程序的第一个viewcontorllweer,(在我的情况下)导致不稳定的行为,这就是为什么有时iOS应用程序停止响应时,从手表收到消息的主要原因。
3 – 重新启动会话build议只在主机应用程序上进行。 这是我的iOS应用程序只有一个WCSessionDelegate的例子。 (AppDelegate)
#pragma mark - WCSessionDelegate - (void)session:(WCSession *)session activationDidCompleteWithState:(WCSessionActivationState)activationState error:(NSError *)error{ if( activationState == WCSessionActivationStateActivated) { NSLog(@"iPhone WKit session Activated"); }else if (activationState == WCSessionActivationStateInactive) { NSLog(@"iPhone WKit Inactive"); }else if (activationState == WCSessionActivationStateNotActivated) { NSLog(@"iPhone WKit NotActivated"); } } - (void)sessionDidBecomeInactive:(WCSession *)session{ /* The session calls this method when it detects that the user has switched to a different Apple Watch. While in the inactive state, the session delivers any pending data to your delegate object and prevents you from initiating any new data transfers. After the last transfer finishes, the session moves to the deactivated state */ NSLog(@"sessionDidBecomeInactive"); if (session.hasContentPending) { NSLog(@"inactive w/ pending content"); } } - (void)sessionDidDeactivate:(WCSession *)session{ // Begin the activation process for the new Apple Watch. [[WCSession defaultSession] activateSession]; //perform any final cleanup tasks related to closing out the previous session. } - (void)sessionReachabilityDidChange:(WCSession *)session{ NSLog(@"sessionReachabilityDidChange"); }
最后一件事,写下相应的方法签名,如果你需要从watch的回复发送数据,拿回应的方法签名:…根据apple的以下方法
sendMessage:replyHandler:errorHandler:, sendMessageData:replyHandler:errorHandler:, and transferCurrentComplicationUserInfo:
具有更高的优先级,并立即传输。 您的应用程序收到的所有消息都将在后台线程上串行传递到会话委托。
因此,不要浪费时间在iOS appDelegate上的mainQueue上分配回复对象,等到您的watchOS上有响应并将其更改为主线程以相应地更新您的UI。