我目前正在编写一个实用程序,作为其中的一部分,接收一个字符串(通过 WebSockets 和 Starscream 库),然后将字符串值显示在 SwiftUI 视图(名为 ReadingsView)中。
代码的结构如下 - 有两个类,管理 WebSocket 连接的 WSManager 类和具有 ObservableObject 属性的 GetReadings 类,它管理和存储读数。
当使用 WSManager 类中的 didReceive 方法接收到字符串时,它被 WSManager 类中的 decodeText 方法解码,然后调用 GetReadings 类中的 parseReceivedStrings 方法。
class WSManager : WebSocketDelegate {
func didReceive(event: WebSocketEvent, client: WebSocket) {
case .text(let string):
// Decode the text
DispatchQueue.main.async {
self.decodeText(recvText: string)
print("Received text: \(string)")
}
recvString = string
}
func decodeText(recvText: String) {
// If the message is allowed, then pass it to getReadings
print("Decoding")
if recvText.hasPrefix("A=") {
getReadings.parseReceivedStrings(recvText: recvText, readingType: .allreadings)
print("All readings received")
} else if recvText.hasPrefix("T = ") {
getReadings.parseReceivedStrings(recvText: recvText, readingType: .temperature)
} else if recvText.hasPrefix("P = ") {
getReadings.parseReceivedStrings(recvText: recvText, readingType: .pressure)
} else if recvText.hasPrefix("H = ") {
getReadings.parseReceivedStrings(recvText: recvText, readingType: .humidity)
} else {
print("Unrecognised string.")
}
}
}
enum ReadingType {
case allreadings
case temperature
case pressure
case humidity
}
class GetReadings: ObservableObject {
let objectWillChange = ObservableObjectPublisher()
@Published var temp: Float = 0.0 {
willSet {
print("Temp new = " + String(temp))
objectWillChange.send()
}
}
@Published var pressure: Float = 0.0 {
willSet {
print("Pressure new = " + String(pressure))
objectWillChange.send()
}
}
@Published var humidity: Float = 0.0 {
willSet {
print("Humidity new = " + String(humidity))
objectWillChange.send()
}
}
func getAll() {
//print(readings.count)
//print(readings.count)
wsManager.socket.write(string: "get_all")
}
func parseReceivedStrings (recvText: String, readingType: ReadingType) {
if readingType == .allreadings {
// Drop first two characters
let tempText = recvText.dropFirst(2)
// Split the string into components
let recvTextArray = tempText.components(separatedBy: ",")
// Deal with the temperature
temp = (recvTextArray[0] as NSString).floatValue
// Pressure
pressure = (recvTextArray[1] as NSString).floatValue
// Humidity
humidity = (recvTextArray[2] as NSString).floatValue
}
}
}
解析值时,我希望 ReadingsView 中的值会立即更新,因为我已将变量标记为 @Published,并使用 objectWillChange 属性手动推送更改。willSet 参数中的打印语句反映了新值,但文本不会更新。在 ReadingsView 代码中,我通过在按下刷新按钮时手动调用 parseReceivedString 方法来弥补这一点(这用作 WebSocket 协议的一部分来发送请求),但这会导致读数落后于它们的位置应该。理想情况下,我希望读数在用上一段中描述的方法解析后立即更新。
struct ReadingsView: View {
@ObservedObject var getReadings: GetReadings
var body: some View {
VStack {
Text(String(self.getReadings.temp))
Text(String(self.getReadings.pressure))
Text(String(self.getReadings.humidity))
Button(action: {
print("Button clicked")
self.getReadings.getAll()
self.getReadings.parseReceivedStrings(recvText: wsManager.recvString, readingType: .allreadings)
}) {
Image(systemName: "arrow.clockwise.circle.fill")
.font(.system(size: 30))
}
.padding()
}
}
}
我想知道我是否使用了正确的声明,或者我尝试做的是否与使用多个类不兼容——这是我第一次使用 SwiftUI,所以我可能会遗漏一些细微差别。提前谢谢你的帮助。
编辑 - 添加代码
内容视图
struct ContentView: View {
@State private var selection = 0
var body: some View {
TabView(selection: $selection){
ReadingsView(getReadings: GetReadings())
.tabItem {
VStack {
Image(systemName: "thermometer")
Text("Readings")
}
} .tag(0)
SetupView()
.tabItem {
VStack {
Image(systemName: "slider.horizontal.3")
Text("Setup")
}
}
.tag(1)
}
}
}