SwiftUI中调用ORSSerialPort.send无法连接串口向Arduino发送数据
问题修复方案
代码核心问题
- 未给
ORSSerialPort设置delegate:你虽然声明了遵守ORSSerialPortDelegate协议,但没有给串口实例赋值delegate,ORSSerial的部分底层通信逻辑依赖delegate配置 - 端口打开状态判断逻辑错误:
if ((serialPort?.isOpen) != nil)仅能判断串口实例存在,无法确认端口真的打开,实际只要serialPort不为空,这个判断永远为真 - 实例生命周期管理错误:SwiftUI视图的普通存储属性会随着视图重绘被反复销毁重建,你的
myPort实例刚初始化打开端口,可能立刻触发deinit关闭端口,自然无法正常发送数据 - 发送时机不符合Arduino特性:绝大多数Arduino开发板在串口连接建立时会自动重启,重启耗时约1-2秒,刚打开端口就发数据,Arduino还没完成启动,根本收不到指令
修复后完整代码
import SwiftUI import ORSSerial // 继承ObservableObject让SwiftUI可以稳定管理实例生命周期 class MyPort: NSObject, ORSSerialPortDelegate, ObservableObject { var serialPort: ORSSerialPort? let myData = "2".data(using: .utf8) override init(){ super.init() // 初始化串口 guard let port = ORSSerialPort(path: "/dev/cu.usbmodem14101") else { print("Error: 获取串口失败,请检查设备路径是否正确") return } serialPort = port // 必须设置delegate serialPort?.delegate = self serialPort?.baudRate = 9600 serialPort?.numberOfDataBits = 8 serialPort?.numberOfStopBits = 1 serialPort?.parity = .none serialPort?.usesRTSCTSFlowControl = false print("正在打开串口...") serialPort?.open() } // 监听串口打开成功的回调,在回调中处理发送逻辑 func serialPortWasOpened(_ serialPort: ORSSerialPort) { print("串口已打开,等待Arduino重启完成后发送数据...") // 延迟1.5秒发送,等待Arduino重启完成 DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [weak self] in guard let self = self, let data = self.myData else { return } self.serialPort?.send(data) print("已发送数据: \(String(describing: data))") } } func serialPortWasRemovedFromSystem(_ serialPort: ORSSerialPort) { print("Error: 串口被拔出") self.serialPort = nil } // 新增错误回调方便排查问题 func serialPort(_ serialPort: ORSSerialPort, didEncounterError error: Error) { print("串口出错: \(error.localizedDescription)") } deinit { serialPort?.close() print("串口已关闭") } } struct ContentView: View { // 用@StateObject修饰,保证实例生命周期和视图绑定,不会被意外销毁 @StateObject var sendArduino = MyPort() var body: some View { VStack(spacing: 20){ Text("串口通信测试") // 新增手动发送按钮方便调试 Button("手动发送指令") { guard let data = sendArduino.myData, let port = sendArduino.serialPort, port.isOpen else { print("串口未打开,发送失败") return } port.send(data) print("手动发送成功") } } .frame(width: 400, height: 400) } }
调试提示
- 如果仍运行失败,先确认串口路径是否正确,路径会随USB口插入位置变化,可以在终端执行
ls /dev/cu.usbmodem*查看当前设备路径 - 确认Arduino代码的波特率、校验位、停止位参数和Swift代码设置完全一致
- 可以先打开Arduino IDE的串口监视器发送
2测试硬件逻辑正常后,再运行SwiftUI代码测试
内容的提问来源于stack exchange,提问作者fredlock
相关产品推荐
相关产品推荐

