我最近在我的应用程序上遇到了困难,我认为这是因为我在构想中遗漏了一些东西。我对 OOP 相当陌生,可能这是我的错,但我不能说它在哪里。
问题是我的应用程序中有不同的视图,它们显示 @Observable 类的属性。由于某种原因,在不同的视图中,我看到显示的值不同,而所有值都必须相同,因为它来自可观察类的相同属性。我正在使用共享实例,我知道这是不正确的,但我尝试过使用 @Environment 并直接注入类实例,但它都是一样的。显然这是我的错,我非常感谢我错在哪里。
情况是这样的——为了原理,我简单描述一下。 我有一个处理 UDP 套接字连接的类。在该类中,我收到一个字符串,该字符串将被进一步处理。每秒都会收到字符串。
class UDPHandler {
//use shared instance - I know it is not correct methods
var fromNMEA = NMEAReader.share
func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext filterContext: Any?) {
if let receivedString = String(data: data, encoding: .utf8) {
//here I receive the string, this function is being triggered and the string is pass to a function in another class which will handle further actions with the string
fromNMEA.processRawString(rawData: receivedString)
}
}
然后我有 @Observable 类,它存储要显示的所有属性以及处理来自 UDPHandler 的字符串的函数
@Observable class NMEAReader {
//create shared instance
static let shared = NMEAReader()
var boatSpeedLag = Double() //value to be displayed
//there are a lot more values but it doesn't work even with one
func processRawString(rawData: String){
//here I make different manipulations over the string, take the values, convert them to Doubles, calculate different things and update all the properties declared
}
//even more support functions here ... and so on.
}
接下来是视图部分。我有几个在 ContentView 中调用的视图
struct ContentView {
//shared instance so I can get to the observable class
var nmea = NMEAReader.shared
var body: some View {
//portrait view, where I pass the shared instance
PortraitView(nmea: nmea).opacity((horizontalSizeClass == .compact && verticalSizeClass == .regular) ? 1 : 0)
}
}
struct PortraitView {
VStack{
//this is a separate settings menu from where I start the socket communication
NavigationLink(destination: SettingsMenu()) {
Image(systemName: "gear")
.dynamicTypeSize(.xxxLarge)
.foregroundStyle(Color(UIColor.systemGray))
}
//all views are of the same type, with a single Text line where I just display the value. They are so many, so I can compare and see what is going on, in reality views are different. I pass to them the shared instance of the NMEAReader class so they can update when it changes
HStack{
SmallDisplayCell(nmea: nmea)
SmallDisplayCell(nmea: nmea)
}
HStack{
SmallDisplayCell(nmea: nmea)
SmallDisplayCell(nmea: nmea)
SmallDisplayCell(nmea: nmea)
}
HStack{
SmallDisplayCell(nmea: nmea)
SmallDisplayCell(nmea: nmea)
SmallDisplayCell(nmea: nmea)
}
}
}
然后我有 SettingsMenu(),我可以在其中开始/停止与外界的通信。
struct SettingsMenu: View {
//initialize an instance of the UDPHandler, so I can start/stop the communication
private var connector = UDPHandler()
var body: some View {
VStack(){
Button("Start") {
connector.start()
}
Button("Stop") {
connector.stop()
}
}
}
}
SmallDisplayView 对于测试来说非常简单,但在实际应用程序中也没有那么复杂。
struct SmallDisplayCell: View {
var nmea: NMEAReader
var value = Double()
var body: some View {
Text(String(nmea.boatSpeedLag))
.frame(width: width, height: width, alignment: .center)
}//END OF BODY
}//END OF STRUCTURE
就是这样。但我无法同时更新显示单元的所有视图。 请看图片,这样你就能明白我在说什么。
任何关于 OOP 的想法和建议以及我如何实现该结构将不胜感激,谢谢。