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.