SwiftUI 视图未正确刷新

问题描述 投票:0回答:1

我最近在我的应用程序上遇到了困难,我认为这是因为我在构想中遗漏了一些东西。我对 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 的想法和建议以及我如何实现该结构将不胜感激,谢谢。

swift oop swiftui observable mainview
1个回答
0
投票

所以,在我阅读了这篇文章并实施了 workingdog 支持乌克兰 的建议后,我最终得到了以下配置:

  1. 将 UDPHandler 类功能移至 NMEAReader() 内,这是我的可观察类。
  2. 在环境中包含 NMEAReader() 实例,我可以在应用程序的不同视图中访问它。
  3. 调用 udpSocket 函数接收 DispatchQueue.main.async {} 块中的数据。否则视图不会同步更新,就会变得一团糟。

完成上述所有操作后,它就像一个魅力,完全符合预期。不过,这并不奇怪,来自workingdog支持乌克兰的建议和建议总是正确且有教育意义的,再次感谢。

这就是我想要得到的结果:

© www.soinside.com 2019 - 2024. All rights reserved.