获取数组数据并填充到滚动视图会引发错误
Getting array data and populate to scroll view throws errors
我正在尝试查看消息数组中的消息并将新消息附加到其中。但它会抛出错误。如何解决?
因此,基本上当用户将消息键入 textbox
时,它将保存在数组中,然后填充到 scrollView
以便用户可以查看所有消息。
错误:实例方法'onChange(of:perform:)'要求'Binding'符合'Equatable'
import SwiftUI
var messagesDBArray : [SingleMessageBubbleModel] = []
struct SingleMessageBubbleModel: Identifiable { //need codable?
let id = UUID()
var text: String
var received: Bool
var timeStamp: Date
}
struct ContentView: View {
@Binding private var lastMessageID: UUID
messagesDBArray.append(SingleMessageBubbleModel(text: "this is first message", received: true, timeStamp: Date()))
messagesDBArray.append(SingleMessageBubbleModel(text: "this is second message", received: true, timeStamp: Date()))
var body: some View {
VStack {
ScrollViewReader { proxy in
ScrollView {
ForEach(messagesDBArray, id: \.id) { message in
MessageBubble(message: message)
}
}
.padding(.top, 10)
.background(.white)
.onChange(of: $lastMessageID) { id in
withAnimation {
proxy.scrollTo(id, anchor: .bottom)
}
}
}
}
.background(Color.gray)
}
}
struct MessageBubble: View {
var message: SingleMessageBubbleModel
@State private var showTime = false
var body: some View {
VStack(alignment: message.received ? .leading : .trailing) {
HStack {
Text(message.text)
.padding()
.background(message.received ? Color.gray : Color.blue)
.cornerRadius(30)
}
.frame(maxWidth: 300, alignment: message.received ? .leading : .trailing)
.onTapGesture {
withAnimation {
showTime.toggle()
}
}
if showTime {
Text("\(message.timeStamp.formatted(.dateTime.hour().minute()))")
.font(.caption2)
.foregroundColor(.gray)
.padding(message.received ? .leading : .trailing, 25)
}
}
.frame(maxWidth: .infinity, alignment: message.received ? .leading : .trailing)
.padding(message.received ? .leading : .trailing)
.padding(.horizontal, 4)
}
}
试试这个方法:
import SwiftUI
@main
struct TestApp: App {
@State var theUUID = UUID() // <-- here
var body: some Scene {
WindowGroup {
ContentView(lastMessageID: $theUUID) // <-- here
}
}
}
struct ContentView: View {
@Binding var lastMessageID: UUID // <-- here no private, could also use `@State`
@State var messagesDBArray : [SingleMessageBubbleModel] = [] // <-- here inside the view
var body: some View {
VStack {
ScrollViewReader { proxy in
ScrollView {
ForEach(messagesDBArray, id: \.id) { message in
MessageBubble(message: message)
}
}
.padding(.top, 10)
.background(.white)
.onChange(of: lastMessageID) { id in // <-- here no $
withAnimation {
proxy.scrollTo(id, anchor: .bottom)
}
}
}
}
.background(Color.gray)
// -- here
.onAppear {
messagesDBArray.append(SingleMessageBubbleModel(text: "this is first message", received: true, timeStamp: Date()))
messagesDBArray.append(SingleMessageBubbleModel(text: "this is second message", received: true, timeStamp: Date()))
}
}
}
我建议您再次阅读教程:https://developer.apple.com/tutorials/swiftui/
请注意,由于您没有更改 lastMessageID
,您可以(推荐)使用 @State var lastMessageID: UUID
在您的 ContentView
而不是绑定中,这实际上取决于您要做什么。
我正在尝试查看消息数组中的消息并将新消息附加到其中。但它会抛出错误。如何解决?
因此,基本上当用户将消息键入 textbox
时,它将保存在数组中,然后填充到 scrollView
以便用户可以查看所有消息。
错误:实例方法'onChange(of:perform:)'要求'Binding'符合'Equatable'
import SwiftUI
var messagesDBArray : [SingleMessageBubbleModel] = []
struct SingleMessageBubbleModel: Identifiable { //need codable?
let id = UUID()
var text: String
var received: Bool
var timeStamp: Date
}
struct ContentView: View {
@Binding private var lastMessageID: UUID
messagesDBArray.append(SingleMessageBubbleModel(text: "this is first message", received: true, timeStamp: Date()))
messagesDBArray.append(SingleMessageBubbleModel(text: "this is second message", received: true, timeStamp: Date()))
var body: some View {
VStack {
ScrollViewReader { proxy in
ScrollView {
ForEach(messagesDBArray, id: \.id) { message in
MessageBubble(message: message)
}
}
.padding(.top, 10)
.background(.white)
.onChange(of: $lastMessageID) { id in
withAnimation {
proxy.scrollTo(id, anchor: .bottom)
}
}
}
}
.background(Color.gray)
}
}
struct MessageBubble: View {
var message: SingleMessageBubbleModel
@State private var showTime = false
var body: some View {
VStack(alignment: message.received ? .leading : .trailing) {
HStack {
Text(message.text)
.padding()
.background(message.received ? Color.gray : Color.blue)
.cornerRadius(30)
}
.frame(maxWidth: 300, alignment: message.received ? .leading : .trailing)
.onTapGesture {
withAnimation {
showTime.toggle()
}
}
if showTime {
Text("\(message.timeStamp.formatted(.dateTime.hour().minute()))")
.font(.caption2)
.foregroundColor(.gray)
.padding(message.received ? .leading : .trailing, 25)
}
}
.frame(maxWidth: .infinity, alignment: message.received ? .leading : .trailing)
.padding(message.received ? .leading : .trailing)
.padding(.horizontal, 4)
}
}
试试这个方法:
import SwiftUI
@main
struct TestApp: App {
@State var theUUID = UUID() // <-- here
var body: some Scene {
WindowGroup {
ContentView(lastMessageID: $theUUID) // <-- here
}
}
}
struct ContentView: View {
@Binding var lastMessageID: UUID // <-- here no private, could also use `@State`
@State var messagesDBArray : [SingleMessageBubbleModel] = [] // <-- here inside the view
var body: some View {
VStack {
ScrollViewReader { proxy in
ScrollView {
ForEach(messagesDBArray, id: \.id) { message in
MessageBubble(message: message)
}
}
.padding(.top, 10)
.background(.white)
.onChange(of: lastMessageID) { id in // <-- here no $
withAnimation {
proxy.scrollTo(id, anchor: .bottom)
}
}
}
}
.background(Color.gray)
// -- here
.onAppear {
messagesDBArray.append(SingleMessageBubbleModel(text: "this is first message", received: true, timeStamp: Date()))
messagesDBArray.append(SingleMessageBubbleModel(text: "this is second message", received: true, timeStamp: Date()))
}
}
}
我建议您再次阅读教程:https://developer.apple.com/tutorials/swiftui/
请注意,由于您没有更改 lastMessageID
,您可以(推荐)使用 @State var lastMessageID: UUID
在您的 ContentView
而不是绑定中,这实际上取决于您要做什么。