You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift Combine:监听数组内对象属性变化及元素新增方法

解决方案

要实现监听数组元素的新增及每个元素的isUploaded变化,最终在所有元素的isUploaded为true时启用发送按钮,可以借助Combine的CombineLatestMany(你提到的便捷工具)来合并多个发布者,配合flatMapLatest处理数组的动态变化。

完整实现代码

import Combine

class FileUploadCellViewModel {
    @Published var isUploaded: Bool = false
}

class FileUploadScreenViewModel: ObservableObject {
    @Published var viewModels: [FileUploadCellViewModel] = []
    @Published var isSendButtonEnabled: Bool = false
    private var cancellables: Set<AnyCancellable> = []

    init() {
        // 监听viewModels数组变化,合并所有cellViewModel的isUploaded状态
        let allUploadedPublisher = $viewModels
            .flatMapLatest { viewModels in
                // 数组为空时默认返回false(可根据需求调整)
                guard !viewModels.isEmpty else {
                    return Just(false).eraseToAnyPublisher()
                }
                // 合并所有cell的isUploaded发布者,任意一个变化时返回所有状态的数组
                return Publishers.CombineLatestMany(viewModels.map { $0.$isUploaded })
                    // 判断所有状态是否全为true
                    .map { $0.allSatisfy { $0 } }
                    .eraseToAnyPublisher()
            }
            // 初始状态设为false
            .prepend(false)
        
        // 假设isDateCorrectPublisher是你的日期验证发布者,这里用Just(true)作为示例
        let isDateCorrectPublisher = Just(true).eraseToAnyPublisher()

        allUploadedPublisher
            .combineLatest(isDateCorrectPublisher)
            .sink { [weak self] allUploaded, dateCorrect in
                self?.isSendButtonEnabled = allUploaded && dateCorrect
            }
            .store(in: &cancellables)
    }
}

// 测试逻辑
let screen = FileUploadScreenViewModel()
let viewModel1 = FileUploadCellViewModel()
let viewModel2 = FileUploadCellViewModel()

screen.viewModels.append(viewModel1) // isSendButtonEnabled: false
screen.viewModels.append(viewModel2) // isSendButtonEnabled: false

viewModel1.isUploaded = false // isSendButtonEnabled: false
viewModel2.isUploaded = true // isSendButtonEnabled: false
viewModel1.isUploaded = true // isSendButtonEnabled: true

关键逻辑说明

  • flatMapLatest:每次viewModels数组发生变化(新增/删除元素)时,会自动取消之前的订阅,并创建新的合并发布者,保证始终监听当前数组内的所有元素。
  • CombineLatestMany:将数组中每个FileUploadCellViewModel的$isUploaded发布者合并成一个,当任意一个元素的isUploaded变化时,会发出所有元素当前的isUploaded状态数组。
  • allSatisfy:遍历状态数组,判断是否所有元素的isUploaded都为true,直接转换成布尔值输出。
  • prepend(false):给发布者设置初始值,避免数组为空或初始状态下按钮误启用。

内容的提问来源于stack exchange,提问作者Kacper Cz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 01:41:26