WatchConnectivity接收苹果手表心率消息类型转换失败及报错求助
问题详情
- 开发过程中触发
((Any) throws -> Bool) throws -> Optional<Any> cannot conform to 'BinaryInteger'类型不匹配报错 - 项目为苹果手表采集心率同步至iPhone的示例项目,当前卡在WatchConnectivity会话传输的
[String: Any]类型消息转换环节,已研究WatchConnectivity相关开发逻辑3天 - 已验证手表端消息可正常传输到iOS端,仅差消息接入心率更新逻辑,初步判定
guard let语句导致didReceiveMessage函数提前终止 - 确认只要将
["rate": 61]格式的消息解包为Double类型的数值61,即可通过guard let校验保证函数正常执行


- 存在附加报错
NO with WCErrorCodeDeliveryFailed,已按照现有公开方案调整逻辑仍会复现,经判断该报错与上述类型转换问题无关联
现有代码(iOS端WatchKitConnection.swift)
import Foundation import WatchConnectivity protocol WatchKitConnectionDelegate: AnyObject { func didFinishedActiveSession() func updateLatestHeartRate(_ LatestHeartRate: Double) } protocol WatchKitConnectionProtocol { func startSession() func sendMessage(message: [String : AnyObject], replyHandler: (([String : AnyObject]) -> Void)?, errorHandler: ((NSError) -> Void)?) } class WatchKitConnection: NSObject { static let shared = WatchKitConnection() weak var delegate: WatchKitConnectionDelegate? private override init() { super.init() } func sendHeartRate(rate: Int) { WCSession.default.sendMessage(["rate": rate], replyHandler: nil) { error in print("Failed to send message: \(error)") } print("from iOS watchkit connection") } } extension WatchKitConnection: WatchKitConnectionProtocol { func startSession() { session?.delegate = self session?.activate() } func sendMessage(message: [String : AnyObject], replyHandler: (([String : AnyObject]) -> Void)? = nil, errorHandler: ((NSError) -> Void)? = nil) { validReachableSession?.sendMessage(message, replyHandler: { (result) in print(result) print("success in phone sendmessage function") }, errorHandler: { (error) in print("error in phone sendmessage function") print(error) }) } } extension WatchKitConnection: WCSessionDelegate { func session(_ session: WCSession, didReceiveMessage message: [String : Any]) { print("didReceiveMessage from watch") print(message) delegate?.updateLatestHeartRate(Double(message.values.first)) guard let heartRate = message.values.first as? String? else { return } guard let heartRateDouble = Double(heartRate!) else { return } print("printing heartRate double from message\(heartRateDouble)") delegate?.updateLatestHeartRate(heartRateDouble) print("updateLatestHeartRate") } }
修复方案
核心问题原因
手表端发送的心率值为Int类型,原有代码错误尝试将Int值转为String类型,导致guard let校验失败提前返回,同时message.values.first为Any类型,无法直接传入Double构造器触发类型不匹配报错。
修正代码
- 先在
WatchKitConnection类内补充缺失的WCSession相关属性
class WatchKitConnection: NSObject { static let shared = WatchKitConnection() weak var delegate: WatchKitConnectionDelegate? // 补充session定义 private let session: WCSession? = WCSession.isSupported() ? WCSession.default : nil // 补充可用会话判断属性 private var validReachableSession: WCSession? { guard let session = session, session.isReachable else { return nil } return session } // 原有其他代码不变 private override init() { super.init() } // ... }
- 替换原有
didReceiveMessage方法逻辑
func session(_ session: WCSession, didReceiveMessage message: [String : Any]) { print("didReceiveMessage from watch") print(message) // 直接按key取值,避免遍历values取到错误值 guard let heartRate = message["rate"] as? Int else { return } // Int转Double无需二次解析 let heartRateDouble = Double(heartRate) print("printing heartRate double from message\(heartRateDouble)") delegate?.updateLatestHeartRate(heartRateDouble) print("updateLatestHeartRate") }
修改后即可解决类型不匹配报错,guard let校验不会提前终止函数运行。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

