【问题标题】:SwiftUI can not add onChange eventSwiftUI 无法添加 onChange 事件
【发布时间】:2020-07-01 21:56:24
【问题描述】:

我有一个视图,其中显示了我的消息列表。每当添加新消息时,我都想滚动到底部。我正在尝试将 onChange 事件添加到 ForEach 但这会破坏我的代码并出现一些奇怪的错误:Referencing instance method 'onChange(of:perform:)' on 'Array' requires that 'Message' conform to 'Equatable' 有时是 The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions 当我删除 onChange 时,一切都符合要求。

这是Message 模型:

struct Message: Identifiable {
    var id = UUID()
    var text: String
    var createdAt: Date = Date()
    var senderID: String
    var seen: Bool
    
    init(dictionary: [String: Any]) {
        self.text = dictionary["text"] as? String ?? ""
        self.senderID = dictionary["senderID"] as? String ?? ""
        self.seen = dictionary["seen"] as? Bool ?? false
    }
}

我在这里做错了什么?

`ForEach

struct MessagesView: View {
    @ObservedObject var messagesViewModel: MessagesViewModel
    
    var body: some View {
        VStack {
            ScrollView(.vertical, showsIndicators: false, content: {
                ScrollViewReader { reader in
                    VStack(spacing: 20) {
                        ForEach(messagesViewModel.request.messages) { message in
                            Text(message.text)
                                .id(message.id)
                        }
                        .onChange(of: messagesViewModel.request.messages) { (value) in
                            reader.scrollTo(value.last?.id)
                        }
                    }
                }
            })
        }
    }
}

【问题讨论】:

  • 我在教程中看到了这个,但那个人没有这样做。此外,我认为这不是错误,因为这种错误往往会产生误导。

标签: ios swift swiftui xcode12


【解决方案1】:

如果您的messages@Published,则以下内容应该可以工作(正如我在Make a list scroll to bottom with SwiftUI 中测试的那样)

struct MessagesView: View {
    @ObservedObject var messagesViewModel: MessagesViewModel
    
    var body: some View {
        VStack {
            ScrollView(.vertical, showsIndicators: false, content: {
                ScrollViewReader { reader in
                    VStack(spacing: 20) {
                        ForEach(messagesViewModel.request.messages) { message in
                            Text(message.text)
                                .id(message.id)
                        }
                        .onReceive(messagesViewModel.request.$messages) { (value) in
                           guard !value.isEmpty else { return } 
                           reader.scrollTo(value.last!.id)
                        }
                    }
                }
            })
        }
    }
}

【讨论】:

    猜你喜欢
    • 2015-10-16
    • 1970-01-01
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 2018-11-13
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多