简体   繁体   中英

Push the navigation link with the updated @published variable

I updated the published var chats in a sheet. And when the sheet is dismissed (by button press), the MessageView navigates to ChatView . I hope to use that updated chats in the ChatView , but now when it's first pushed, chats isn't updated, until you go back and push the view again. Is there a way to get around?

getAllChats is the observableobject with var chats

class getAllChats : ObservableObject{
    
    @Published var chats = [Chat]()
    
    @EnvironmentObject var userInfo : UserData
    
    init() {
        
        let db = Firestore.firestore()
        let currentid = Auth.auth().currentUser!.uid
        
        db.collection("users").document(currentid).getDocument { (document, err) in
            if let document = document {
                
                //all chat ids
                if let chatIDs = document.get("chats") as? [String]{
                    
                    for chatid in chatIDs{ //download chat from chat ids
                        db.collection("chats").document(chatid).getDocument { (doc, error) in
                            if let doc = doc{
                                let frienduid = doc.get("user1") as! String == currentid ? doc.get("user2") as! String : doc.get("user1") as! String
                                let friendname = doc.get("user1") as! String == currentid ? doc.get("user2_username") as! String : doc.get("user1_username") as! String
                                
                                let friend = FetchedUser.init()
                                friend.uid = frienduid
                                friend.username = friendname
                                
                                //parse msg
                                var messages: [Message] = []
                                
                                let messagesArr = doc.get("messages") as! [[String:Any]]
                                for msg in messagesArr {
                                    messages.append(Message.fromDB(object: msg))
                                }
                                
                                //create chat
                                let chat = Chat.init(friend: friend, messages: [])
                                self.chats.append(chat)
                                print(self.chats.count)
                            }
                        }
                    }
                }
            }
        }
    }
}

MessageView

    struct MessagingView: View {
    @State var addChat = false //show search user view
    @State var showNewChat = false
   
    @State var addedUser = FetchedUser.init()

    @ObservedObject var chatsData = getAllChats()
    
    @EnvironmentObject var userInfo: UserData
    
    init(){
        UITableView.appearance().tableFooterView = UIView()
        UITableView.appearance().separatorStyle = .none
    }
    
    @ViewBuilder
    var body: some View {
        VStack{
            List(chatsData.chats, id: \.chatID){ chat in
                NavigationLink(destination: ChatView(chat: chat)) {
                    ChatCellView(chat: chat)
                }
            }
            
            //navigate to a new chat
            if !chatsData.chats.isEmpty{
            NavigationLink(destination: ChatView(chat: chatsData.chats[0]), isActive: $showNewChat){
                Text("")
            }
            }
            
        }
        .navigationBarItems(trailing: Button(action: {
                        self.addChat.toggle()
                    }, label: {
                        Image(systemName: "plus.circle.fill")
                            .font(.headline)
                    }).accentColor(.white))
                                                  
                        .sheet(isPresented: $addChat) {
                            AddChatView(addedUser: self.$addedUser, addChat: self.$addChat, showNewChat: self.$showNewChat)
                                .environmentObject(self.userInfo)
                            
        }
                    
    }
}


struct ChatCellView: View{
    var chat: Chat
    
    var body: some View{
        VStack(spacing: 0){
            HStack{
                Image(systemName: "person.crop.circle")
                    .font(.title)
                    .padding()
                
                VStack(alignment: .leading){
                    Text(chat.friend.username)
                        .font(.headline)
                    
                    HStack{
                        Text(chat.mostRecentMessage()?.body ?? "Tap to chat")
                            .font(.body)
                            .padding(.trailing, 10)
                        
                        Spacer()
                    }
                }
                
                Circle()
                    .fill(isUnread() ? Color.navIconColor : Color.clear)
                    .frame(width: 12, height: 12)
                
                Spacer()
            }
        }
    }
    
    func isUnread() -> Bool{
        if let mostRecentMessage = chat.mostRecentMessage() {
            return !mostRecentMessage.hasRead && mostRecentMessage.recipient == "user"
        }
        return false
    }
    
}

ChatView

struct ChatView: View{
    
    var chat: Chat

    @State var write = ""
    
    var body: some View {
        VStack {
            List(chat.messages) { i in
                ListMessage(msg: i.body, sentFromUser: i.sender == "user")
            }
            .navigationBarTitle(
                Text(chat.friend.username), displayMode: .inline)
                .accentColor(.white)
           
            
            HStack {
                TextField("message...",text: self.$write).padding(10)
                    .background(Color(red: 233.0/255, green: 234.0/255, blue: 243.0/255))
                    .cornerRadius(25)
                
                Button(action: {
                    if self.write.count > 0 {
                        //self.message.addInfo(msg: self.write, user: self.name, image: self.image)
                        self.write = ""
                    } else {
                        
                    }
                }) {
                    Image(systemName: "paperplane.fill").font(.system(size: 20))
                        .foregroundColor((self.write.count > 0) ? Color.navIconColor : Color.gray)
                        .rotationEffect(.degrees(50))
                    
                }
            }.padding()
        }.padding(.top)
         .modifier(AdaptsToKeyboard())
    }
}

struct ListMessage : View {
    
    var msg = ""
    
    var sentFromUser = false
    
    var body: some View {
        
        HStack {
            if sentFromUser {
                Spacer()
                
                HStack {
                    Text(msg).padding(10).background(Color.secondary)
                        .cornerRadius(18)
                        .foregroundColor(.white)
                    
                    
                }
            } else {
                HStack {
                    
                    Text(msg).padding(10).background(Color.titleBarColor)
                        .cornerRadius(28)
                        .foregroundColor(.white)
                    
                }
                Spacer()
            }
        }
    }
}

I assume the link is toggled too early, so instead of activate link by binding in sheet, try to activate it after sheet got dismissed

Here is a way (scratchy, as provided snapshot is not testable)

.sheet(isPresented: $addChat, 
       onDismiss: { self.$showNewChat }) {  // << here
    
    // refactor AddChatView to remove dependency on showNewChat
    AddChatView(addedUser: self.$addedUser, addChat: self.$addChat)
        .environmentObject(self.userInfo)
}

So the problem is you want to update the chatView with new chats which is in object chat

And you are not observing chat inside ChatView , but you are observing chat inside Messageview , so it cannot update inside ChatView . That's th reason its updating when you are going back to messageView

so you need to convert your chat to a ObservedObject to listed its publisher.

struct ChatView: View{
    
    @ObservedObject var chat: Chat

    @State var write = ""
...................
............

}

and also you need to modify Chat (individual) to be a ObservableObject in its class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM