【发布时间】:2020-04-30 10:04:23
【问题描述】:
有时我的视图模型使用@Published 属性或PassthroughSubject,但我不希望这对外界是可写的。很简单,把它变成一个公共的AnyPublisher 并保持可写的私有,像这样:
class ViewModel {
@Published private var _models = ["hello", "world"]
var models: AnyPublisher<[String], Never> {
return $_models.eraseToAnyPublisher()
}
}
let viewModel = ViewModel()
viewModel.models.sink { print($0) }
但是,如果您还希望能够“按需”读取值怎么办?例如对于这种情况:
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(viewModel.models[indexPath.row])
}
}
显然,上面的代码不起作用。
我考虑过使用CurrentValueSubject,但它的值也是可写的,而且无论如何我都很难将 Publisher 变成 CurrentValueSubject。
我目前的解决方案是在视图模型上添加类似这样的内容:
class ViewModel {
@Published private var _models = ["hello", "world"]
@Published var selectedIndex: Int?
var models: AnyPublisher<[String], Never> {
return $_models.eraseToAnyPublisher()
}
var selectedModel: AnyPublisher<String, Never> {
return models.combineLatest($selectedIndex.compactMap { $0 }).map { value, index in
value[index]
}.eraseToAnyPublisher()
}
}
let viewModel = ViewModel()
viewModel.models.sink { print($0) }
viewModel.selectedModel.sink { print($0) }
viewModel.selectedIndex = 1
但是添加selectedIndex 属性、selectedModel 发布者、设置 selectedIndex 并订阅发布者有点麻烦。所有这些都是因为我希望能够读取viewModel.models 的当前值(并且不可写)。
有更好的解决方案吗?
【问题讨论】: