【问题标题】:how to subscribe to a function, which observes @Published?如何订阅观察@Published的函数?
【发布时间】:2020-07-13 07:08:50
【问题描述】:

需要在 SwiftUI 的 body 块中动态渲染消息列表:

 var chatSpace: some View {
        List(self.viewModel.getMessages(), id: \.self) { message in
            message
        }
 }

其中视图模型,是以下类的实例:

class MessagesListViewModel: ObservableObject {
    
    @ObservedObject var messageService: MessageService
    
    init(messageService: MessageService) {
        self.messageService = messageService
    }
    
    func getMessages() -> [MessageView] {
        return self.messageService.messages.map {
            return MessageView(message: $0)
        }
    }
    
    
}

我想在更新 MessageService message 属性时反映更改,我该如何实现?我可以以某种方式订阅更改吗?现在,我基本上是通过更新messages发布的var来添加一条消息,但是它不会触发重新绘制

class MessageService: ObservableObject
{
    @Published var messages: [Message] = [Message]()
    
    func addMessage(_ sender: String, _ text: String, _ time: String) {
        self.messages.append(Message(sender: sender, text: text, time: time))
    }
}

【问题讨论】:

    标签: swiftui combine


    【解决方案1】:

    现在,我基本上是通过更新发布的消息变量来添加消息,但是,它不会触发重新绘制

    因为@ObservedObject var messageService: MessageServiceMessagesListViewModel 中什么都不做,因为@ObservedObject 设计为在视图中但不在视图模型中。

    所以解决方案应该是(消息的分离视图)

    struct ChatSpace: some View {
       @ObservedObject var messageService: MessageService    // << view observes messages
    
       var body: some View {
          List(messageService.messages, id: \.self) {
                MessageView(message: $0)
          }
       }
    }
    

    【讨论】:

    • 谢谢你,这行得通!但是如果那是一个函数,而不是一个观察到的对象,我将如何处理呢?比方说,需要在视图中包装普通数据吗?是否有可能以某种方式调用主体中的函数,或订阅该函数?
    • @Ilja,如果它返回一些视图,它可以在主体中调用函数,但观察必须始终在视图内部。首选的方法是分离到另一个视图而不是使用函数,因为在第一种情况下,SwiftUI 渲染引擎具有更好的优化能力。
    猜你喜欢
    • 1970-01-01
    • 2019-04-14
    • 1970-01-01
    • 2012-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    • 2018-11-26
    相关资源
    最近更新 更多