SwiftUI中如何在视图与代理类中使用全局变量实现温度值UI更新
问题原因
- 存在多个互不关联的
GlobalTs28b实例:视图层使用的是TakeTemperatureTS28BUIView里通过@StateObject创建的实例,而ts28bControllerDelegate、SaveTemp函数里都单独初始化了新的GlobalTs28b实例,修改其中一个实例的属性不会同步到其他实例,自然无法触发视图刷新。 - 蓝牙代理回调默认在后台线程执行,直接在后台线程修改
@Published属性,SwiftUI不会触发视图更新。 String(describing: valueFinal)的写法会输出带冗余信息的字符串,也可能导致显示异常。
解决方法
1. 统一使用同一个GlobalTs28b实例
修改ts28bControllerDelegate的初始化方法,接收外部传入的GlobalTs28b实例,不要内部自行创建:
class ts28bControllerDelegate: NSObject, TS28BControllerDelegate { // 其他原有属性保留 let global: GlobalTs28b // 去掉原来的自行初始化代码 // 修改初始化方法 init(global: GlobalTs28b) { self.global = global super.init() // 原有初始化逻辑保留 print("ENTRA EN StartDiscoverTS28B") controllerTS28B = TS28BController.shared() controllerTS28B.delegate = self } // 其他原有方法保留 }
2. 修改工具函数,接收外部实例
修改iHealthAuthTS28B函数:
func iHealthAuthTS28B(global: GlobalTs28b) { // 原有逻辑保留,修改delegate初始化代码 let delegate = ts28bControllerDelegate(global: global) // 后续原有逻辑保留 }
修改SaveTemp函数:
func SaveTemp(global: GlobalTs28b){ print("ENTRA EN GUARDAR DE TEMPERATURA") print("VALOR: ", global.temp) }
3. 主线程更新UI相关属性,优化温度字符串格式
修改温度回调方法:
public func controller(_ controller: TS28BController?, device: TS28B?, didUpdateTemperature value: Float, temperatureUnit unit: TemperatureUnit, measure date: Date?, measureLocation type: TemperatureType) { print("Temperature UNIDAD:", unit) print("Temperature:", value) // 确认单位转换逻辑,如果传入值已经是摄氏度可以去掉转换 let valueFinal = ((value - 32) * 5/9) // 优化字符串格式,保留1位小数 let stringFloat = String(format: "%.1f", valueFinal) // 切换到主线程赋值,触发SwiftUI刷新 DispatchQueue.main.async { self.global.temp = stringFloat print("centigadros:", self.global.temp) } }
4. 修改视图层调用逻辑
修改ContentView2的onAppear和按钮点击事件,传入当前环境中的GlobalTs28b实例:
// onAppear修改 .onAppear { iHealthAuthTS28B(global: global) } // 按钮点击修改 Button(action:{ SaveTemp(global: global) }){ // 原有按钮UI代码保留 }
其他优化建议
- 页面消失时调用
controllerTS28B.stopScan()并断开设备连接,避免内存泄漏和重复回调。 - 若多次进入该页面,注意判断
TS28BController的代理是否已经被其他对象占用,避免回调丢失。
内容的提问来源于stack exchange,提问作者Laura Ramírez
相关产品推荐
相关产品推荐

