BLE设备无数据时Runmefit SDK回调未执行致App崩溃的解决咨询
方案1:修复闭包内的强制转换与空值校验
将闭包内的强制类型转换改为可选绑定,同时提前过滤空数据场景,避免无意义的SDK调用:
public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { print("Received: \(String(describing: characteristic.value))") guard let writeCharacter = writeCharacter else { print("No write characteristic found") return } // 提前过滤空数据,直接通知RN侧无数据 guard let characteristicValue = characteristic.value, !characteristicValue.isEmpty else { let emptyDataDict: [String: Any] = [ ST_RevType_Key: NSNumber(value: REV_TYPE.noData.rawValue), // 需确保枚举有对应值,无则自定义临时值 ST_ErrorType_Key: NSNumber(value: ERROR_TYPE.success.rawValue) ] NotificationCenter.default.post( name: NSNotification.Name(Nof_Revice_Data_Key), object: nil, userInfo: emptyDataDict ) return } let nsError = error as NSError? ?? NSError(domain: "", code: 0, userInfo: nil) STBlueToothData.sharedInstance().notifyRunmefit( peripheral, writeCharacter: writeCharacter, characteristic: characteristic, error: nsError, complete: { (error, revType, errorType, responseObject) in // 安全转换error参数,避免nil强制转NSError崩溃 guard let nsError = error as NSError? else { let resultDict: [String: Any] = [ ST_RevType_Key: NSNumber(value: revType.rawValue), ST_ErrorType_Key: NSNumber(value: errorType.rawValue) ] NotificationCenter.default.post( name: NSNotification.Name(Nof_Revice_Data_Key), object: responseObject, userInfo: resultDict ) return } if nsError.code != 0 { print("Error: \(nsError)") } else { let resultDict: [String: Any] = [ ST_RevType_Key: NSNumber(value: revType.rawValue), ST_ErrorType_Key: NSNumber(value: errorType.rawValue) ] NotificationCenter.default.post( name: NSNotification.Name(Nof_Revice_Data_Key), object: responseObject, userInfo: resultDict ) } } ) }
方案2:添加回调超时机制
用DispatchWorkItem实现超时逻辑,避免SDK回调永远不执行导致的未知问题:
public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { print("Received: \(String(describing: characteristic.value))") guard let writeCharacter = writeCharacter else { print("No write characteristic found") return } guard let characteristicValue = characteristic.value, !characteristicValue.isEmpty else { // 空数据处理逻辑同方案1 let emptyDataDict: [String: Any] = [ ST_RevType_Key: NSNumber(value: REV_TYPE.noData.rawValue), ST_ErrorType_Key: NSNumber(value: ERROR_TYPE.success.rawValue) ] NotificationCenter.default.post( name: NSNotification.Name(Nof_Revice_Data_Key), object: nil, userInfo: emptyDataDict ) return } let nsError = error as NSError? ?? NSError(domain: "", code: 0, userInfo: nil) // 创建超时任务 let timeoutWorkItem = DispatchWorkItem { [weak self] in guard let self = self else { return } print("notifyRunmefit callback timeout") // 发送超时通知给RN侧 let timeoutDict: [String: Any] = [ ST_RevType_Key: NSNumber(value: REV_TYPE.timeout.rawValue), // 需确保枚举有对应值 ST_ErrorType_Key: NSNumber(value: ERROR_TYPE.timeout.rawValue) ] NotificationCenter.default.post( name: NSNotification.Name(Nof_Revice_Data_Key), object: nil, userInfo: timeoutDict ) } // 3秒后触发超时(可根据需求调整时长) DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: timeoutWorkItem) STBlueToothData.sharedInstance().notifyRunmefit( peripheral, writeCharacter: writeCharacter, characteristic: characteristic, error: nsError, complete: { [weak self] (error, revType, errorType, responseObject) in // 回调执行时取消超时任务 timeoutWorkItem.cancel() guard let self = self else { return } // 安全处理参数逻辑同方案1 guard let nsError = error as NSError? else { let resultDict: [String: Any] = [ ST_RevType_Key: NSNumber(value: revType.rawValue), ST_ErrorType_Key: NSNumber(value: errorType.rawValue) ] NotificationCenter.default.post( name: NSNotification.Name(Nof_Revice_Data_Key), object: responseObject, userInfo: resultDict ) return } if nsError.code != 0 { print("Error: \(nsError)") } else { let resultDict: [String: Any] = [ ST_RevType_Key: NSNumber(value: revType.rawValue), ST_ErrorType_Key: NSNumber(value: errorType.rawValue) ] NotificationCenter.default.post( name: NSNotification.Name(Nof_Revice_Data_Key), object: responseObject, userInfo: resultDict ) } } ) }
方案3:优化闭包生命周期管理
在闭包捕获列表中添加[weak self],避免循环引用导致的内存泄漏,同时确保闭包内访问self时的安全性。
额外注意事项
- 如果
REV_TYPE和ERROR_TYPE没有对应noData/timeout的枚举值,可自定义临时值传递给RN侧,或联系SDK厂商补充枚举定义 - 测试空数据场景时,需确认BLE设备确实返回空的特征值,避免误判
- 可在
didUpdateValueFor方法中添加更多日志,排查SDK的异常行为
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

