在 Swift Combine 中创建顺序发布者

Creating a sequential publisher in Swift Combine

我想去抖动一批事件并在延迟约 1.5 秒后处理它们。这是我所做的。

class ViewModel: ObservableObject {

    @Published var pending: [TaskInfo]
    private var cancellable: AnyCancellable? = nil

    init() {
        processPendingTasks()
    }

    func queueTask(task: TaskInfo) { 
        pending.append(task)
    }

    private func processPendingTasks() {
        cancellable = $pendingTasks
                .debounce(for: 1.5, scheduler: RunLoop.main)
                .sink(receiveValue: { batch in 
                    // Iterate though elements and process events.
                })           
    }
}

问题: 这工作正常,但我遇到的问题是它执行不必要的视图更新,因为数组被标记为 @Published.

我在寻找什么: 理想的方法是流式设置,我可以在其中获取所有事件(以批处理方式),但 sink 应该等待添加最后一个事件后的 1.5 秒。

我尝试了 PassthroughSubject,但它似乎只让我获取了过去 1.5 秒内发生的最后一个事件。

一个可能的解决方案是 PassthroughSubjectcollect 运算符的组合。在 queueTask 中将任务发送给主题。

func queueTask(task: TaskInfo) { 
    subject.send(task)
}

收到最后一个项目后 1.5 秒发送

subject.send(completion: .finished)

并订阅

subject
.collect()
.sink { [weak self] tasks in 
   self?.pending = tasks
 } 

如果传入任务的间隔小于 1.5 秒,您还可以使用 .timeout(1.5) 运算符在超时间隔后终止管道。