有时,我的视图模型使用了@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
,但是它的值也是可写的,而且无论如何我都很难将发布者变成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
(并且不可写)。
有更好的解决方案吗?
答案 0 :(得分:1)
为什么不将@Published
属性设为公开,而将其设置程序设为私有?这应该完全满足您的要求,同时还可以使代码最少且干净。
class ViewModel {
@Published public private(set) var models = ["hello", "world"]
}
let viewModel = ViewModel()
viewModel.$models.sink { print($0) }