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
相关产品推荐
相关产品推荐

