SwiftUI:在没有安装在View上的情况下删除StateObject的对象,这将每次创建一个新示例[重复]

1wnzp6jl  于 5个月前  发布在  Swift
关注(0)|答案(1)|浏览(39)

此问题在此处已有答案

Accessing StateObject's object without being installed on a View. This will create a new instance each time - SwiftUI(3个答案)
18天前关闭
我对SwiftUI相当陌生,我正在尝试构建一个聊天室。当我向应用程序发送消息时,新消息不会显示,并且我在终端中收到一个警告,说“在未安装在View上的情况下删除StateObject的对象。这将每次创建一个新示例。”

import SwiftUI
import SocketIO

struct ChatMessage: Hashable {
    var message: String
    var MatchImg: String
    var isMe: Bool

}

class ChatMessageList: ObservableObject {
    @Published var list: [ChatMessage]
    
    init(list: [ChatMessage]) {
        self.list = list
    }
    
    func addItem(item: ChatMessage) {
        list.append(item)
        objectWillChange.send()
    }
}

struct MessageView: View {
    @State private var showMenu: Bool = false
    @StateObject var messages = ChatMessageList(list: [
        ChatMessage(message: "Hello world", MatchImg:"ye",isMe: true),
        ChatMessage(message: "Hello world", MatchImg:"ye",isMe: false)
    ])
    
    @State private var composedMessage: String = ""
    let roomID: String
    let userID: String
    let otherUser: String
    
    private var socket: SocketIOClient
    private var manager: SocketManager
    
    init(roomID: String, userID: String, otherUser: String) {
        self.roomID = roomID
        self.userID = userID
        self.otherUser = otherUser
        
        self.manager = SocketManager(socketURL: URL(string: "http://localhost:8080")!, config: [.log(false), .compress])
        self.socket = self.manager.defaultSocket
        
        self.socket.connect()
        
        self.addHandlers()
        
        
    }

    func addHandlers() {
        self.socket.on("chat message") { data, ack in
            let messageText = data[0]

            let newMessage = ChatMessage(message: messageText as! String, MatchImg: "ye", isMe: false)
            addMessage(message: newMessage)
            
//            DispatchQueue.main.async {
//                self.messages.list.append(newMessage)
//            }
            
           
        }
    }
    
    func addMessage(message: ChatMessage) {
        DispatchQueue.main.async {
            messages.addItem(item: message)
        }
    }
    
    var body: some View {
        VStack {
            VStack(alignment: .center){
                    //omitted
                }
                
                List{
                    ForEach(messages.list, id: \.self) { msg in
                        ChatRow(chatMessage: msg)
                            .listRowSeparator(.hidden)
                            .listRowBackground(Color.clear)
                    }
                    
                }
                .padding(0)
                .listStyle(PlainListStyle())
                .environment(\.defaultMinListRowHeight, 0)
                
                
                
                
                HStack {
                    TextField("Message...", text: $composedMessage).frame(minHeight: CGFloat(36))
                        .padding(.horizontal,12)
                        .overlay(
                            RoundedRectangle(cornerRadius: 15)
                                .stroke(Color.blue, lineWidth: 2)
                        )
                    Button("Send"){
                        Task {
                            self.socket.emit("message", roomID, composedMessage)
                            self.messages.addItem(item: ChatMessage(message: composedMessage, MatchImg: "ye", isMe: true))
                            print(self.messages)
                            self.composedMessage = ""
                        }
                    }
                    Button("add") {
                        showMenu.toggle()
                    }
                    Button(action: {}){
                        Image("person.fill")
                            .foregroundColor(Color.black)
                        
                    }
                }.padding(20)
                    .task{
                        print(self.socket.status)
                        self.socket.emit("identify", userID)
                        
                        self.socket.emit("subscribe", roomID, otherUser)
                    }
            }
        }
    }
    
}

struct ChatRow : View {
    var chatMessage: ChatMessage
    var body: some View {
        if !chatMessage.isMe {
            
            HStack {
                // omitted
            }
        }
        else {
             // omitted
       }

    }
}

字符串
我试过

  • 使用DispatchQueue.main.async
  • 编写一个单独的函数来添加新消息(addMessage()
  • 在类ChatMessageList中编写一个函数

我在添加了一个新项目后打印了状态对象,但是没有新的消息。但是在发送新消息时,上面的所有功能似乎都工作得很好。

hgqdbh6s

hgqdbh6s1#

你不应该在View结构体中初始化像SocketManager这样的对象,你也不能在View结构体中使用DispatchQueue.main.asyncView数据结构体只是简单的值,它们会被生成、区分和销毁。所以如果你在它们中创建对象,它会被认为是内存泄漏,如果它真的这样做了,调度器将返回到一些旧的丢失的View结构体上。

相关问题