连接MQTT Broker时遇CocoaMQTT错误:deliver delegate为nil,帧被丢弃
解决CocoaMQTT错误:The deliver delegate is nil!!!
以下是针对问题的具体修复步骤:
1. 修复MQTTManager实例被提前释放的问题
你在sendTelemetryMsg中创建的MQTTManager是局部变量,函数执行完毕后会被ARC自动回收,导致CocoaMQTT的代理对象消失,触发deliver delegate is nil错误。需要将MQTTManager声明为类属性,避免提前释放:
class YourClass: NSObject { private var mqttManager: MQTTManager? // 声明为类属性,延长生命周期 @objc(sendTelemetryMsg:withUrl:withResolver:withRejecter:) func sendTelemetryMsg(password: String, url: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void { mqttManager = MQTTManager() // 后续操作移至连接成功回调中 } }
2. 修正CocoaMQTT初始化的参数错误
你的connectMQTT方法中,clientID和host参数完全写反了,还多了一个多余的双引号,这会导致连接到错误的Broker地址:
func connectMQTT() { // 正确参数顺序:clientID是自定义客户端标识,host是Broker地址 mqtt = CocoaMQTT(clientID: "your-client-id-435345", host: "broker.hivemq.com", port: 1883) mqtt.delegate = self mqtt.connect() }
3. 延迟订阅、发布操作到连接成功后
MQTT连接是异步操作,不能在调用connect()后立即执行订阅和发布,必须等待didConnectAck回调确认连接成功后再执行:
第一步:在MQTTManager中添加连接成功回调
class MQTTManager: CocoaMQTTDelegate { var mqtt: CocoaMQTT! var onConnected: (() -> Void)? // 新增连接成功回调闭包 // ... 其他代理方法保持不变 func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) { if ack == .accept { print("Connected to the MQTT!") onConnected?() // 触发连接成功回调 } else { print("Failed to connect to MQTT, ack code: \(ack.rawValue)") } } }
第二步:在调用方法中绑定回调执行操作
@objc(sendTelemetryMsg:withUrl:withResolver:withRejecter:) func sendTelemetryMsg(password: String, url: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void { mqttManager = MQTTManager() mqttManager?.onConnected = { [weak self] in guard let self = self else { reject("ERROR", "Manager deallocated", nil) return } let topic = "your-topic" self.mqttManager?.subscribeToTopic(topic: topic) let message = "Hello, IoT Device!" self.mqttManager?.publishData(topic: topic, message: message) resolve("Message published successfully") } // 处理连接失败场景 mqttManager?.mqttDidDisconnect = { _, err in if let err = err { reject("CONNECT_FAILED", err.localizedDescription, err) } } mqttManager?.connectMQTT() }
完整修正后的MQTTManager代码
import Foundation import CocoaMQTT class MQTTManager: CocoaMQTTDelegate { var mqtt: CocoaMQTT! var onConnected: (() -> Void)? var mqttDidDisconnect: ((CocoaMQTT, Error?) -> Void)? func mqtt(_ mqtt: CocoaMQTT, didPublishAck id: UInt16) { print("Published message with ID: \(id)") } func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopics success: NSDictionary, failed: [String]) { print("Subscribed to topics: \(success)") } func mqtt(_ mqtt: CocoaMQTT, didUnsubscribeTopics topics: [String]) { print("Unsubscribed from topics: \(topics)") } func mqttDidPing(_ mqtt: CocoaMQTT) { print("Pinged!") } func mqttDidReceivePong(_ mqtt: CocoaMQTT) { print("Ponged!") } func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: (any Error)?) { print("Disconnected from the MQTT: \(err?.localizedDescription ?? "No error")") mqttDidDisconnect?(mqtt, err) } func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) { if ack == .accept { print("Connected to the MQTT!") onConnected?() } else { print("Failed to connect to MQTT, ack code: \(ack.rawValue)") } } func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) { print("Data published successfully") } func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16) { if let messageString = message.string { print("Received message on topic \(message.topic): \(messageString)") } } func connectMQTT() { mqtt = CocoaMQTT(clientID: "your-client-id-435345", host: "broker.hivemq.com", port: 1883) mqtt.delegate = self mqtt.connect() } func subscribeToTopic(topic: String) { mqtt.subscribe(topic) } func publishData(topic: String, message: String) { mqtt.publish(topic, withString: message, qos: .qos1) } }
内容的提问来源于stack exchange,提问作者user26952423
相关产品推荐
相关产品推荐

