获取数组数据并填充到滚动视图会引发错误

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 而不是绑定中,这实际上取决于您要做什么。