Иногда моя модель представления использует свойство @Published
или PassthroughSubject
, но я не хочу, чтобы это было доступно для записи во внешний мир. Достаточно просто, превратить его в publi c 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.
Мое текущее решение состоит в том, чтобы добавить что-то подобное в viewmodel:
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
(и не иметь возможности записи).
Есть ли лучшие решения?