WatchKit Extension代理方法未实现问题求助
我正在通过一个简单应用学习WatchKit Connectivity,已经花了两天时间排查以下错误,但毫无进展:{app name}_WatchKit_Extension.InterfaceController does not implement delegate method。我完全复制了苹果官方的SimpleWatchConnectivity示例代码,也查了各类论坛,但都没解决。
我的代码能正常构建运行,但在手表端执行iOS ViewController里的这段代码时出现错误:
if (WCSession.isSupported()) { WCSession.default.delegate = self; WCSession.default.activate() if let messageText = textField.text{ WCSession.default.sendMessage(["message": messageText] ,replyHandler: {replyMessage in print(replyMessage) } , errorHandler: {error in print( error.localizedDescription)} ) } }
报错信息
手表端(仅发送第二条消息时出现,第一条无报错):
2018-01-06 10:39:20.522995+1100 messageDemo WatchKit Extension[338:743006] [WC] -[WCSession onqueue_handleDictionaryMessageRequest:withPairingID:]_block_invoke delegate messageDemo_WatchKit_Extension.InterfaceController does not implement delegate method
2018-01-06 10:39:20.524378+1100 messageDemo WatchKit Extension[338:743006] [WC] -[WCSession _onqueue_sendResponseError:identifier:dictionaryMessage:] identifier: A150D814-453C-44B7-B970-913697526D6A with WCErrorCodeDeliveryFailed
手机端调试时的报错:
2018-01-07 09:47:23.319221+1100 messageDemo[6628:1549809] [WC] -[WCSession _onqueue_notifyOfMessageError:messageID:withErrorHandler:] (null) errorHandler: YES with WCErrorCodeSessionNotActivated
2018-01-07 09:47:23.321103+1100 messageDemo[6628:1549978] [WC] -[WCSession _onqueue_notifyOfMessageError:messageID:withErrorHandler:]_block_invoke dropping as pairingIDs no longer match. pairingID (null), client pairingID: (null)
WatchConnectivity session has not been activated.
我的InterfaceController代码:
import WatchKit import Foundation import WatchConnectivity class InterfaceController: WKInterfaceController , WCSessionDelegate { func session(_ session: WCSession , activationDidCompleteWith activationState: WCSessionActivationState , error: Error?) { print("activationDidCompleteWith:\(activationState )") } func sessionReachabilityDidChange(_ session: WCSession) { // print("sessionReachabilityDidChange") } @IBOutlet var messageLabel: WKInterfaceLabel! override func awake(withContext context: Any?) { super.awake(withContext: context) } override func willActivate() { super.willActivate() if (WCSession.isSupported()) { WCSession.default.delegate = self; WCSession.default.activate() } } override func didDeactivate() { super.didDeactivate() } private func session(session: WCSession, didReceiveMessage message: [String : Any] , replyHandler: @escaping ([String : Any]) -> Void) { self.messageLabel.setText(message["message"]! as? String) } func session(_ session: WCSession, didReceiveMessage message: [String : Any]) { self.messageLabel.setText(message["message"]! as? String) } func session(_ session: WCSession, didReceiveMessageData messageData: Data) { print("HERE01") } func session(_ session: WCSession, didReceiveMessageData messageData: Data, replyHandler: @escaping (Data) -> Void) { self.session(session, didReceiveMessageData: messageData) print("HERE02") } func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) { print("HERE03") } func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:]) { print("HERE04") } func session(_ session: WCSession, didFinish userInfoTransfer: WCSessionUserInfoTransfer, error: Error?) { print("HERE05") } func session(_ session: WCSession, didReceive file: WCSessionFile) { print("HERE06") } func session(_ session: WCSession, didFinish fileTransfer: WCSessionFileTransfer, error: Error?) { print("HERE07") } }
我加了多个打印语句覆盖所有场景,但还是出现上述错误。恳请各位提供技术帮助。
问题分析与解决方案
兄弟,我一眼就看到你代码里的两个关键问题,这就是导致报错的根源:
1. Delegate方法签名错误(手表端报错的核心原因)
你写的带replyHandler的didReceiveMessage方法是旧的Objective-C风格签名,还加了private修饰符,WatchConnectivity框架根本识别不到这个方法!
正确的Swift 3+方法签名应该是这样的:
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) { self.messageLabel.setText(message["message"] as? String) // 必须调用replyHandler!否则手机端会一直等待响应,最终触发超时错误 replyHandler(["status": "message received successfully"]) }
你原来的方法少了参数前的_,而且private修饰符会让系统无法识别这个delegate方法,一定要去掉。
2. 手机端Session激活时机错误(导致WCErrorCodeSessionNotActivated)
你在手机端代码里调用activate()后立刻发送消息,但activate()是异步操作!Session还没完成激活流程就发消息,自然会报错。
正确的做法是:在手机端的WCSessionDelegate里实现activationDidCompleteWith方法,等激活完成后再发送消息。给你个手机端ViewController的示例:
import UIKit import WatchConnectivity class ViewController: UIViewController, WCSessionDelegate { @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() if WCSession.isSupported() { WCSession.default.delegate = self WCSession.default.activate() } } // 实现这个方法,确认Session激活完成 func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { if let error = error { print("Session激活失败: \(error.localizedDescription)") return } print("Session激活成功: \(activationState)") } // 假设你有一个发送按钮的点击事件 @IBAction func sendMessageTapped(_ sender: UIButton) { guard let messageText = textField.text, !messageText.isEmpty else { return } // 发送前先检查Session是否激活且可达 guard WCSession.default.isActivated, WCSession.default.isReachable else { print("Session未激活或不可达") return } WCSession.default.sendMessage(["message": messageText], replyHandler: { reply in print("收到回复: \(reply)") }, errorHandler: { error in print("发送失败: \(error.localizedDescription)") }) } // iOS端必须实现这两个必填的delegate方法 func sessionDidBecomeInactive(_ session: WCSession) {} func sessionDidDeactivate(_ session: WCSession) { session.activate() // 重新激活,处理切换配对等场景 } }
3. 额外优化建议
- 手表端的
willActivate每次界面激活都会调用,重复设置delegate和activate()虽然不会崩溃,但建议移到awake(withContext:)里,只初始化一次。 - 发送消息前一定要检查
WCSession.default.isReachable,确保手表和手机处于连接状态。 - 所有带
replyHandler的消息必须调用replyHandler,否则会触发超时错误。
按照上面的修改,你应该就能解决这两个报错了!
内容的提问来源于stack exchange,提问作者BlastWave

