В настоящее время у меня Observable
, созданный с использованием scan
для обновления базовой модели с использованием PublishSubject
, например:
class ViewModel {
private enum Action {
case updateName(String)
}
private let product: Observable<Product>
private let actions = PublishSubject<Action>()
init(initialProduct: Product) {
product = actions
.scan(initialProduct, accumulator: { (oldProduct, action) -> Product in
var newProduct = oldProduct
switch action {
case .updateName(let name):
newProduct.name = name
}
return newProduct
})
.startWith(initialProduct)
.share()
}
func updateProductName(_ name: String) {
actions.onNext(.updateName(name))
}
private func getProductDetail() {
/// This will call a network request
}
}
Каждое "локальное" действие, такое как обновление названия продукта, цены ... выполняется с помощью метода, подобного updateProductName(_ name: String)
выше. Но что, если я хочу получить сетевой запрос, который также обновляет продукт и может вызываться каждый раз, когда я хочу, например, после нажатия кнопки или после вызова updateProductName
?
// ОБНОВЛЕНИЕ: После прочтения комментария iWheelBuy и ответа Даниэля я в итоге использовал еще 2 действия
class ViewModel {
private enum Action {
case getDetail
case updateProduct(Product)
}
///....
init(initialProduct: Product) {
product = actions
.scan(initialProduct, accumulator: { (oldProduct, action) -> Product in
var newProduct = oldProduct
switch action {
case .updateName(let name):
newProduct.name = name
case .getDetail:
self.getProductDetail()
case .updateProduct(let p):
return p
}
return newProduct
})
.startWith(initialProduct)
.share()
}
func getProductDetail() {
actions.onNext(.getDetail)
}
private func getProductDetail(id: Int) {
ProductService.getProductDetail(id) { product in
self.actions.onNext(.updateProduct(product))
}
}
}
Но я чувствую, что я запускаю побочный эффект (вызов сетевого запроса) внутри scan
, без обновления модели, это что-то не так?
Также, как я могу использовать сетевой запрос "rx"?
// What if I want to use this method instead of the one above,
// without subscribe inside viewmodel?
private func rxGetProductDetail(id: Int) -> Observable<Product> {
return ProductService.rxGetProductDetail(id: Int)
}