You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中如何解析BLE通知并通过回调执行CoreData存储操作?

SwiftUI中BLE无响应请求的通知回调处理方案

需求:实现BLE交互,手机发送.withoutResponse类型请求,设备通过BLE通知回复,仅在收到设备正常响应后执行CoreData存储操作。

核心思路

利用Swift的异步等待机制(CheckedContinuation),将BLE的回调式通知转换为异步函数,让saveDevice等待设备响应确认后再执行存储操作;同时维护一个请求映射表,确保每个设备的请求能匹配到对应的响应回调。

代码修改步骤

1. 在BLE管理类中添加请求回调映射表

用于暂存等待响应的请求回调,避免多个设备请求混淆:

// 存储等待响应的回调,key为「设备UUID+请求方法」的组合字符串
private var pendingRequests: [String: CheckedContinuation<Bool, Error>] = [:]

2. 修改saveDevice为异步函数

用withCheckedThrowingContinuation挂起函数,等待设备响应:

func saveDevice(identifier: UUID, name: String, type: Int) async throws {
    let requestData = Request.deviceSave(name: name, type: type)
    writeToIdentifier(identifier: identifier, data: requestData)
    
    // 生成唯一请求键,区分不同设备的不同请求(1是DEVICE SAVE对应的method值)
    let requestKey = "\(identifier.uuidString)-1"
    
    // 挂起函数,等待响应回调
    try await withCheckedThrowingContinuation { continuation in
        pendingRequests[requestKey] = continuation
    }
    
    // 只有收到成功响应后,才执行CoreData存储
    CoreDataModel.shared.saveDevice(uuid: identifier, name: name, type: Int16(type))
}

3. 修改parseResponse触发回调

收到设备通知后,匹配对应的请求并处理结果:

func parseResponse(data: Data, identifier: UUID) {
    let method: UInt8 = data.first!
    let requestKey = "\(identifier.uuidString)-\(method)"
    
    // 取出对应的回调,若不存在则直接返回
    guard let continuation = pendingRequests.removeValue(forKey: requestKey) else {
        return
    }
    
    switch method {
    case 1:
        print("Method: DEVICE SAVE")
        let isSuccess = data[5] == 1
        print("Is configured: \(isSuccess)")
        
        if isSuccess {
            // 响应成功,恢复函数执行
            continuation.resume(returning: true)
        } else {
            // 响应失败,抛出错误
            continuation.resume(throwing: NSError(domain: "BLEError", code: -1, userInfo: [NSLocalizedDescriptionKey: "设备保存失败"]))
        }
    default:
        // 处理未知请求类型
        continuation.resume(throwing: NSError(domain: "BLEError", code: -2, userInfo: [NSLocalizedDescriptionKey: "未知请求方法"]))
    }
}

4. 处理设备断开等异常情况

在设备断开时清理pending请求,避免函数永久挂起:

func peripheral(_ peripheral: CBPeripheral, didDisconnectPeripheral error: Error?) {
    let deviceUUID = peripheral.identifier.uuidString
    // 移除该设备的所有等待请求
    pendingRequests.keys.forEach { key in
        if key.starts(with: deviceUUID) {
            if let continuation = pendingRequests.removeValue(forKey: key) {
                let disconnectError = error ?? NSError(domain: "BLEError", code: -3, userInfo: [NSLocalizedDescriptionKey: "设备断开连接"])
                continuation.resume(throwing: disconnectError)
            }
        }
    }
}

5. SwiftUI视图中调用异步函数

用Task包裹异步调用,处理成功/失败场景:

Button("保存设备") {
    Task {
        do {
            try await bleManager.saveDevice(identifier: targetDeviceUUID, name: "我的设备", type: 1)
            print("设备已成功保存至CoreData")
            // 可添加UI提示,比如弹出Toast
        } catch {
            print("保存失败:\(error.localizedDescription)")
            // 显示错误提示
        }
    }
}

内容的提问来源于stack exchange,提问作者Tim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 16:54:54