为什么 scrollTo 在 Int 而不是 Message 自定义对象类型上工作?

Why is scrollTo working on Int and not Message custom object type?

我用 Int 而不是消息尝试了相同的代码,它起作用了。

当我尝试使用消息对象时,出于某种原因它不喜欢它。即使 .id 是 UUID().

消息显示在 scrollView 中,可以手动滚动,但添加消息后不会自动滚动到底部。

我已经尝试在 ForEach 中使用 .self 而不是 .id,翻转 ScrollView 和 ScrollViewReader 的顺序,不在 MessageRow 上使用 .id,在 scrollTo 中向下转换为 UUID,似乎没有任何效果...

我错过了什么?

提前致谢!

             ScrollViewReader { scrollView in
                ScrollView(.vertical) {
                    LazyVStack {
                        ForEach(groupViewModel.messages) { message in
                            MessageRowView(message: message)
                                .padding(.leading)
                        }
                    }
                    .onAppear {
                        if !groupViewModel.messages.isEmpty {
                            if let last = groupViewModel.messages.last {
                                scrollView.scrollTo(last)
                            }
                        }
                    }
                }
            }
struct Message: Codable, Equatable, Identifiable, Hashable {
    let id: UUID
    let sender: FSUser
    let message: String
    let sendDate: Date
}

欢迎来到 Stack Overflow!你错过了一个简单的事实,即 message.id != message?.id。您的 .id(message.id) 是 non-optional UUID,但是 groupViewModel.messages.last?.id 是可选的。因为它们不匹配,所以你不会得到卷轴。我会给你一个更好的。首先,您不需要使用 message.id。您可以简单地比较消息本身,因为 Identifiable 符合 Equatable。因此,您的代码变为:

        ScrollViewReader { scrollView in
            ScrollView(.vertical) {
                LazyVStack {
                    // You can also skip id: \.id as message is Identifiable
                    ForEach(groupViewModel.messages) { message in
                        MessageRowView(message: message)
                            .id(message)
                    }
                }
                .onAppear {
                    DispatchQueue.main.asyncAfter(deadline: .now()) {
                        if !groupViewModel.messages.isEmpty {
                            // Use if let to unwrap the optional
                            if let last = groupViewModel.messages.last {
                                // Use the unwrapped value here
                                scrollView.scrollTo(last)
                            }
                        }
                    }
                }
            }
        }

如果您还没有声明您的结构符合 Identifiable,那就去做吧。我假设你这样做了,但你没有 post 那部分代码,所以我们没有 Minimal, Reproducible Example (MRE)。大多数问题都需要 MRE 才能得到解答,因此请确保您了解那是什么。

编辑:

在查看你的结构时,试试这个:

struct Message: Codable, Equatable, Identifiable, Hashable {
    let id = UUID()
    let sender: FSUser
    let message: String
    let sendDate: Date
}

您可以立即设置 UUID,因为它永远不会改变。此外,这在长 运行 中并不重要,但如果您符合 Identifiable,您将获得 'Equatable' 一致性。