跳到主要内容

错误处理

SDK 所有异步接口均通过 NSError 返回错误信息。本文介绍错误的结构、完整错误码及最佳实践。

错误结构

SDK 返回的 NSError 包含以下字段:

字段说明
domain错误域,格式为 TS[模块名]ErrorDomain,如 TSBleErrorDomain
code错误码(见下方分类)
userInfo[NSLocalizedDescriptionKey]可读的错误描述
userInfo[NSUnderlyingErrorKey]底层原始错误(如有)

回调约定

SDK 的回调有两种模式:

1. TSCompletionBlock(成功/失败二值)

typedef void(^TSCompletionBlock)(BOOL isSuccess, NSError * _Nullable error);
[[TopStepComKit sharedInstance].bleConnector disconnectCompletion:^(BOOL isSuccess, NSError *error) {
if (isSuccess) {
// 操作成功
} else {
[self handleError:error];
}
}];

2. 数据回调(仅 error 参数)

[[TopStepComKit sharedInstance].heartRate getHistoryDataFrom:startDate to:endDate
completion:^(NSArray *records, NSError *error) {
if (error) {
[self handleError:error];
return;
}
// 正常处理 records
}];

通用错误码(TSErrorCode)

适用于所有模块,定义在 TSErrorEnum.h

系统错误(1001–1004)

枚举值Code含义
eTSErrorUnknown1001未知错误
eTSErrorSDKInitFailed1002SDK 初始化失败
eTSErrorLicenseIncorrect1003SDK 证书错误
eTSErrorSDKConfigError1004SDK 配置错误

设备状态错误(2001–2006)

枚举值Code含义处理建议
eTSErrorNotReady2001设备未就绪等待连接完成后重试
eTSErrorLowBattery2002设备电量过低(< 30%)提示用户充电
eTSErrorUnConnected2003设备未连接提示用户重新连接设备
eTSErrorNotSupport2004暂不支持此功能隐藏对应功能入口
eTSErrorNoSpace2005设备空间不足提示用户清理设备存储
eTSErrorIsBusy2006设备繁忙稍后重试

参数错误(3001–3004)

枚举值Code含义
eTSErrorInvalidParam3001参数不存在
eTSErrorParamError3002参数错误
eTSErrorInvalidTypeError3003参数类型错误
eTSErrorParamSizeError3004参数大小错误

数据操作错误(4001–4004)

枚举值Code含义
eTSErrorDataGetFailed4001数据获取失败
eTSErrorDataSetFailed4002数据设置失败
eTSErrorDataFormatError4003数据格式错误
eTSErrorDataIsEmpty4004数据为空

任务错误(5001–5003)

枚举值Code含义处理建议
eTSErrorPreTaskExecuting5001任务执行中(如 OTA)等待任务完成后重试
eTSErrorTaskExecutionFailed5002任务执行失败提示用户重试
eTSErrorTaskNotStarted5003任务未开始检查调用时序

通信错误(6001–6008)

枚举值Code含义处理建议
eTSErrorTimeoutError6001通信超时重试操作
eTSErrorTransmissionInterrupted6002数据传输中断检查设备距离,重试
eTSErrorSignalInterference6003信号干扰或丢失减少干扰源,重试
eTSErrorPacketLoss6004数据包丢失重试操作
eTSErrorProtocolMismatch6005通信协议不匹配升级 SDK 或固件
eTSErrorConnectionReset6006连接被对方重置重新连接设备
eTSErrorBufferOverflow6007通信缓冲区溢出降低发送频率
eTSErrorChannelBusy6008通信通道繁忙稍后重试

用户操作错误(7001)

枚举值Code含义
eTSErrorUserCancelled7001用户取消操作

蓝牙连接错误码(TSBleConnectionError)

蓝牙专属错误,定义在 TSErrorEnum.h,通过 error.code 获取。

参数错误(9001–9004)

枚举值Code含义
eTSBleErrorInvalidRandomCode9001二维码参数错误
eTSBleErrorInvalidUserId9002用户 ID 参数错误
eTSBleErrorInvalidParam9003参数错误
eTSBleErrorInvalidHandle9004无效句柄

通用错误(9101–9106)

枚举值Code含义处理建议
eTSBleErrorUnknown9101未知错误提示用户重试
eTSBleErrorTimeout9102连接超时检查设备是否在范围内,重试
eTSBleErrorDisconnected9103连接意外断开提示用户重新连接
eTSBleErrorOutOfSpace9104存储空间不足提示用户清理设备
eTSBleErrorUUIDNotAllowed9105UUID 不被允许检查设备兼容性
eTSBleErrorAlreadyAdvertising9106已在广播中等待广播结束后重试

权限和系统错误(9201–9206)

枚举值Code含义处理建议
eTSBleErrorBluetoothOff9201蓝牙未开启提示用户打开系统蓝牙
eTSBleErrorBluetoothUnsupported9202蓝牙不支持提示设备不支持蓝牙
eTSBleErrorPermissionDenied9203缺少蓝牙权限引导用户前往「设置」开启蓝牙权限
eTSBleErrorSystemServiceUnavailable9204系统蓝牙服务不可用提示用户重启手机
eTSBleErrorBluetoothStateUnknown9205蓝牙状态未知等待蓝牙就绪后重试
eTSBleErrorBluetoothResetting9206蓝牙正在重置等待重置完成后重试

连接过程错误(9301–9308)

枚举值Code含义处理建议
eTSBleErrorConnectionFailed9301连接失败重试连接
eTSBleErrorGattConnectFailed9302GATT 连接失败重启蓝牙后重试
eTSBleErrorDeviceOutOfRange9303设备不在范围内靠近设备后重试
eTSBleErrorWeakSignal9304信号太弱靠近设备后重试
eTSBleErrorSignalLost9305信号丢失靠近设备后重试
eTSBleErrorConnectionLimitReached9306连接数达到限制断开其他连接后重试
eTSBleErrorUnknownDevice9307未知设备重新扫描并选择设备
eTSBleErrorOperationNotSupported9308操作不支持检查设备固件版本

认证错误(9404–9413、9499)

枚举值Code含义处理建议
eTSBleErrorEncryptionFailed9404加密失败重新绑定设备
eTSBleErrorPeerRemovedPairingInfo9405配对信息被移除重新绑定设备
eTSBleErrorEncryptionTimeout9406加密超时重试连接
eTSBleErrorUserIdMismatch9407用户 ID 不匹配检查 userId 参数
eTSBleErrorBindCancelledByUser9408用户取消绑定引导用户重新操作
eTSBleErrorBindTimeout9409绑定超时重新发起绑定
eTSBleErrorClassicBluetoothNotConnected9410经典蓝牙未连接检查经典蓝牙连接状态
eTSBleErrorLowBatteryCannotDeleteData9411电量不足无法删除数据提示用户充电
eTSBleErrorDeviceFactoryResetting9412设备正在恢复出厂等待恢复完成后重试
eTSBleErrorFactoryResetRequired9413需要恢复出厂才能重新绑定提示用户在设备上恢复出厂设置
eTSBleErrorAuthenticationUnknown9499认证失败(未知原因)重试连接

设备状态错误(9501–9506)

枚举值Code含义处理建议
eTSBleErrorConnectedByOthers9501设备已被其他设备连接提示用户断开其他连接
eTSBleErrorDeviceAlreadyBound9502设备已被绑定提示用户先解绑
eTSBleErrorLowBattery9503设备电量过低提示用户充电
eTSBleErrorDFUMode9504设备进入 DFU 模式等待 DFU 完成或重启设备
eTSBleErrorDeviceSleeping9505设备处于睡眠模式唤醒设备后重试
eTSBleErrorTooManyPairedDevices9506配对设备过多删除部分配对记录

服务和协议错误(9601–9605)

枚举值Code含义处理建议
eTSBleErrorPeripheralNotFound9601未找到对应外设重新扫描设备
eTSBleErrorServiceNotFound9602未找到所需服务检查设备固件版本
eTSBleErrorCharacteristicNotFound9603特征值未找到检查设备固件版本
eTSBleErrorProtocolVersionMismatch9604协议版本不匹配升级 SDK 或固件
eTSBleErrorMtuNegotiationFailed9605MTU 协商失败重试连接

用户操作(9701–9702)

枚举值Code含义
eTSBleErrorDisconnectedByUser9701用户主动断开连接
eTSBleErrorCancelledByUser9702用户取消连接

扫描结束原因(TSScanCompletionReason)

枚举值含义处理建议
eTSScanCompleteReasonTimeout扫描超时提示未找到设备,可重新扫描
eTSScanCompleteReasonBleNotReady蓝牙未就绪等待蓝牙初始化完成后重试
eTSScanCompleteReasonPermissionDenied权限被拒绝引导用户开启蓝牙权限
eTSScanCompleteReasonUserStopped用户主动停止正常结束,无需处理
eTSScanCompleteReasonSystemError系统错误重启蓝牙后重试

功能不支持检查

调用功能接口前,先用 isSupport 检查设备是否支持:

id<TSHeartRateInterface> heartRate = [TopStepComKit sharedInstance].heartRate;

if (![heartRate isSupport]) {
TSLog(@"当前设备不支持心率功能");
return;
}

[heartRate startMeasureWithParam:nil ...];

统一错误处理

建议封装一个统一的错误处理方法:

- (void)handleSDKError:(NSError *)error context:(NSString *)context {
if (!error) return;

TSLog(@"[%@] 错误 domain=%@ code=%ld: %@",
context,
error.domain,
(long)error.code,
error.localizedDescription);

switch (error.code) {
// 权限/蓝牙状态类 → 引导用户操作
case eTSBleErrorPermissionDenied:
case eTSBleErrorBluetoothOff:
[self showBluetoothSettingsAlert];
break;

// 超时/信号类 → 可重试
case eTSBleErrorTimeout:
case eTSBleErrorSignalLost:
case eTSErrorTimeoutError:
[self retryWithDelay];
break;

// 设备繁忙 → 稍后重试
case eTSErrorIsBusy:
case eTSBleErrorChannelBusy:
[self scheduleRetry];
break;

// 功能不支持 → 隐藏入口
case eTSErrorNotSupport:
[self hideUnsupportedFeature:context];
break;

default:
[self showErrorAlert:error.localizedDescription];
break;
}
}

权限错误处理

- (void)showBluetoothSettingsAlert {
UIAlertController *alert = [UIAlertController
alertControllerWithTitle:@"蓝牙未授权"
message:@"请前往「设置 → 隐私 → 蓝牙」开启蓝牙权限"
preferredStyle:UIAlertControllerStyleAlert];

[alert addAction:[UIAlertAction actionWithTitle:@"去设置"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
}]];

[alert addAction:[UIAlertAction actionWithTitle:@"取消"
style:UIAlertActionStyleCancel
handler:nil]];

[self presentViewController:alert animated:YES completion:nil];
}

注意事项

  1. 不要忽略 error 参数:即使 isSuccess = YES,仍应先判断 error 再判断 isSuccess
  2. 在主线程更新 UI:SDK 所有回调均在主线程执行,可直接操作 UI
  3. 区分可恢复错误和不可恢复错误:超时类错误可重试,权限类错误需引导用户操作,硬件不支持类错误应隐藏对应功能入口
  4. 日志上报:建议将 error.domainerror.code 上报到后端,便于排查问题