I'm building a chat app using SwiftUI and I'm having difficulties getting a LazyVStack to work inside a ScrollView. Here are my questions:
Question 1
Where I have .id(message.id)
, why is this id required for scrollView.scrollTo(chatMessageViewModel.arrayOfMessages.last?.id, anchor: .bottom)
to work, when the ForEach is assigning the same id using id: \.1.id
? If I comment out the .id(message.id)
line, scrollView.scrollTo doesn't work.
Question 2:
a) If I comment out the code .id(message.id)
,on an iPhone 6S, I get 11 messages loaded in view, however, the print statement print(message.messageContent)
prints out 22 messages. Why does this happen?
b) Why are the print(message.messageContent)
print statements not printed in order? I thought a LazyVStack would render in vertical order?
c) As I scroll down to reveal the 12th message, I get "Message 23" printed to the console instead of "Message 12". Why is this?
import SwiftUI
struct ChatMessageModel: Identifiable {
var id: String
var messageContent: String
}
class ChatMessageViewModel: ObservableObject {
@Published var arrayOfMessages: [ChatMessageModel] = [ChatMessageModel(id: "1", messageContent: "Message 1"),
ChatMessageModel(id: "2", messageContent: "Message 2"),
ChatMessageModel(id: "3", messageContent: "Message 3"),
ChatMessageModel(id: "4", messageContent: "Message 4"),
ChatMessageModel(id: "5", messageContent: "Message 5"),
ChatMessageModel(id: "6", messageContent: "Message 6"),
ChatMessageModel(id: "7", messageContent: "Message 7"),
ChatMessageModel(id: "8", messageContent: "Message 8"),
ChatMessageModel(id: "9", messageContent: "Message 9"),
ChatMessageModel(id: "10", messageContent: "Message 10"),
ChatMessageModel(id: "11", messageContent: "Message 11"),
ChatMessageModel(id: "12", messageContent: "Message 12"),
ChatMessageModel(id: "13", messageContent: "Message 13"),
ChatMessageModel(id: "14", messageContent: "Message 14"),
ChatMessageModel(id: "15", messageContent: "Message 15"),
ChatMessageModel(id: "16", messageContent: "Message 16"),
ChatMessageModel(id: "17", messageContent: "Message 17"),
ChatMessageModel(id: "18", messageContent: "Message 18"),
ChatMessageModel(id: "19", messageContent: "Message 19"),
ChatMessageModel(id: "20", messageContent: "Message 20"),
ChatMessageModel(id: "21", messageContent: "Message 21"),
ChatMessageModel(id: "22", messageContent: "Message 22"),
ChatMessageModel(id: "23", messageContent: "Message 23"),
ChatMessageModel(id: "24", messageContent: "Message 24"),
ChatMessageModel(id: "25", messageContent: "Message 25")]
}
struct ChatMessagesView: View {
@StateObject var chatMessageViewModel = ChatMessageViewModel()
var body: some View {
ScrollViewReader { scrollView in
ScrollView (.vertical, showsIndicators: true) {
LazyVStack (spacing: 0) {
ForEach(Array(zip(chatMessageViewModel.arrayOfMessages.indices, chatMessageViewModel.arrayOfMessages)), id: \.1.id) { (index, message) in
Text("Index is \(index) with message: \(message.messageContent)")
.padding(.vertical, 20)
.id(message.id)
.onAppear {
print(message.messageContent)
}
}
}
}
.onAppear {
scrollView.scrollTo(chatMessageViewModel.arrayOfMessages.last?.id, anchor: .bottom)
}
}
.environmentObject(chatMessageViewModel)
}
}