【问题标题】:View Does Not Reload When Observed Object Changed观察对象更改时视图不会重新加载
【发布时间】:2021-01-22 12:35:27
【问题描述】:

我正在努力解决我认为很简单的问题。 见下文... 我有一门课——“连接”——这是@Observable。 在 Connect 中,我有一个属性“theMessage”,它是 @Published。

然后我的 ContentView 引用了属性“theMessage” 当应用程序启动时,视图加载正常,但是...... 当按钮是 Connect 中的方法时,会触发但视图不会重新加载。

我认为问题出在“连接”底部的“接收”方法中 在这个方法的关闭中,我可以看到我是调试.. 收到的incomingMessage OK theMethod 设置好 但观点不变

任何帮助或想法将不胜感激

import Foundation
import Network


class Connect: ObservableObject {
    static let sharedInstance = Connect()

private var talking: NWConnection?
private var listening: NWListener?

@Published var theMessage = "Still No Message"

// DEFINE LISTENER
func listenUDP(port: NWEndpoint.Port) {
    do {
        self.listening = try NWListener(using: .udp, on: port)
        self.listening?.stateUpdateHandler = {(newState) in
            switch newState {
            case .ready:
            print("ready")
            default:
            break
            }
        }
        
        self.listening?.newConnectionHandler = {(newConnection) in
            newConnection.stateUpdateHandler = {newState in
                switch newState {
                case .ready:
                print("new connection")
                self.receive(on: newConnection)
                default:
                break
                }
            }
                
            newConnection.start(queue: DispatchQueue(label: "new client"))
            }
        } catch {
    print("unable to create listener")
    }
    self.listening?.start(queue: .main)
}// END OF FUNC - LISTEN TO UDP





// DEFINE ON RECEIVE
func receive(on connection: NWConnection) {
    connection.receiveMessage { (data, context, isComplete, error) in
        if let error = error {
            print(error)
            return
        }
        if let data = data, !data.isEmpty {
            let incomingString = String(decoding: data, as: UTF8.self)
            print("Incoming String -\(incomingString)")
                DispatchQueue.main.async { [weak self] in
                    self?.objectWillChange.send()
                    self?.theMessage = incomingString
                    print(self?.theMessage ?? "Self Got Binned")
            }
        }
    }
    
}// END OF FUNC - RECEIVE




// DEFINE TALKER
func connectToUDP(hostUDP:NWEndpoint.Host,portUDP:NWEndpoint.Port) {
    self.talking = NWConnection(host: hostUDP, port: portUDP, using: .udp)
    self.talking?.stateUpdateHandler = { (newState) in
        switch (newState) {
            case .ready:
            break
            default:
            break
        }
    }
    self.talking?.start(queue: .main)
}// END OF DEFINE TALKER


// SEND A MESSAGE
func sendUDP(_ content: String) {
    let contentToSendUDP = content.data(using: String.Encoding.utf8)
    
    self.talking?.send(content: contentToSendUDP, completion: NWConnection.SendCompletion.contentProcessed(({ (NWError) in
        if (NWError == nil) {
            // code
        } else {
            print("ERROR! Error when data (Type: String) sending. NWError: \n \(NWError!) ")
        }
    })))
}

}// END OF CLASS - CONNECT


    import SwiftUI
import Network

struct ContentView: View {

@ObservedObject var connect = Connect.sharedInstance
let communication = Connect()

var body: some View {
    
    VStack {
        Text("Incoming Message - \(self.connect.theMessage)")
            .padding(100)
            .onAppear(){
                // LISTENER
                let port2U = NWEndpoint.Port.init(integerLiteral: 1984)
                communication.listenUDP(port: port2U)
            }
   
        Button(action: {
            let host = NWEndpoint.Host.init("localhost")
            let port = NWEndpoint.Port.init("1984")
            self.communication.connectToUDP(hostUDP: host, portUDP: port!)
            self.communication.sendUDP("/cue/MyText/start")
        }) {
            Text("smoke")
        }
        
    }// END VSTACK
}// END OF BODY
}// END OF VIEW

【问题讨论】:

    标签: swiftui observable


    【解决方案1】:

    Connect 类中的这段代码创建了一个单例实例

    static let sharedInstance = Connect()
    

    然后View 用这个创建另一个实例

    let communication = Connect()
    

    一个人看不到另一个人在做什么。这就像创造有 2 辆汽车、2 座房子、2 个人。

    删除communication 并替换为connect。观察和使用单例。

    struct ConnectView: View {
    
        @ObservedObject var connect = Connect.sharedInstance
    
        var body: some View {
            
            VStack {
                Text("Incoming Message - \(self.connect.theMessage)")
                    .padding(100)
                    .onAppear(){
                        // LISTENER
                        let port2U = NWEndpoint.Port.init(integerLiteral: 1984)
                        connect.listenUDP(port: port2U)
                    }
           
                Button(action: {
                    let host = NWEndpoint.Host.init("localhost")
                    let port = NWEndpoint.Port.init("1984")
                    self.connect.connectToUDP(hostUDP: host, portUDP: port!)
                    self.connect.sendUDP("/cue/MyText/start")
                }) {
                    Text("smoke")
                }
                
            }// END VSTACK
        }// END OF BODY
    }// END OF VIEW
    

    如果您将有一个单例模式,那么创建类 private 的初始化程序是一个很好的做法。

    将此添加到您的 Connect 类以防止出现此问题。

    private init(){
        
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-25
      • 1970-01-01
      相关资源
      最近更新 更多