View Model 和 View Controller 之间不断触发驱动程序
Driver is being triggered constantly between View Model and View Controller
RxSwift 上的 Driver
有问题。在 ViewController 中有一个正在监听 initTrigger 的视图模型,如下所示。
let initTrigger = rx.viewWillAppear
.mapToVoid()
.asDriverOnErrorJustComplete()
此 initTrigger
用于绑定到视图模型上的另一个 Driver
let shoppingCart: Driver<ShoppingCart>
let shoppingCart = input.initTrigger
.flatMapLatest {
self.getShoppingCartUseCase
.execute()
.asDriver(onErrorJustReturn: ShoppingCart())
}
getShoppingCartUseCase.execute()
returns Observable<ShoppingCart>
并且正在使用 RxRealm 来监听数据库的变化。
回到视图控制器,我已经订阅了 shoppingCart
像这样
output?.shoppingCart
.map {
print("Mapping")
return [=12=].lines.count == 0
}
.asObservable()
.bind(to: goToCartButton.rx.isHidden)
.disposed(by: bag)
我放置 print("Mapping")
是为了意识到在执行修改我的模型并触发我之前提到的 Observable<ShoppingCart>
的操作后,最后一个驱动程序会不断被触发。
我哪里做错了?
感谢您的帮助。
要停止订阅观察者必须执行以下操作之一:
发送错误信息
发送完成的消息
销毁订阅(销毁disposeBag)
在你的情况下 rx.viewWillAppear
也不会 shoppingCart
不发送错误或完成的消息,因为它们是驱动程序
您正确停止订阅的一种方法是销毁旧的 disposeBag
bag = DisposeBag()
但不要忘记在 viewWillAppear 上恢复订阅
其他选项 将在 VC 中有一些标志,例如
var hasAppeared: Bool
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
...
hasAppeared = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisppear(animated)
...
hasAppeared = false
}
并且只是为了添加过滤
output?.shoppingCart
.filter({ [weak self] _ in self?.hasAppeared ?? false })
.map {
print("Mapping")
return [=11=].lines.count == 0
}
.asObservable()
.bind(to: goToCartButton.rx.isHidden)
.disposed(by: bag)
第三种方式是停止从viewModel内部发送
let initTrigger = rx.viewWillAppear
.mapToVoid()
.asDriverOnErrorJustComplete()
let stopTrigger = rx.viewWillDisappear
.mapToVoid()
.asDriverOnErrorJustComplete()
let shoppingCart: Driver<ShoppingCart>
let shoppingCart = Observable.merge(input.initTrigger.map({ true }),
input.stopTrigger.map({ false }))
.flatMapLatest { isRunning in
guard isRunning else {
return .just(ShoppingCart())
}
return self.getShoppingCartUseCase
.execute()
.asDriver(onErrorJustReturn: ShoppingCart())
}
首先你可以使用.distincUntilChanged()
来过滤相同的事件。
其次,检查为什么 .getShoppingCartUseCase
不断发出事件,只要 ShoppingCart 被写入数据库,RxRealm 就会发送更新,所以也许你有一些不必要的写入。确保当你写入领域时使用 .modified
标志,而不是 .all
(只有当项目发生变化时才会覆盖它,如果没有变化则不会引起事件)
如果您确定只需要参加一次活动 - 您可以随时添加 .take(1)
你也称它为 initTrigger
,但在 viewWillAppear
上发送它——当你返回屏幕时可以调用它多次。如果你需要一次,把它放在viewDidLoad
PS 而不是 .asObservable().bind(to:...)
你可以只写 .drive(...)
这是将驱动程序绑定到 ui.
的更简洁的方法
RxSwift 上的 Driver
有问题。在 ViewController 中有一个正在监听 initTrigger 的视图模型,如下所示。
let initTrigger = rx.viewWillAppear
.mapToVoid()
.asDriverOnErrorJustComplete()
此 initTrigger
用于绑定到视图模型上的另一个 Driver
let shoppingCart: Driver<ShoppingCart>
let shoppingCart = input.initTrigger
.flatMapLatest {
self.getShoppingCartUseCase
.execute()
.asDriver(onErrorJustReturn: ShoppingCart())
}
getShoppingCartUseCase.execute()
returns Observable<ShoppingCart>
并且正在使用 RxRealm 来监听数据库的变化。
回到视图控制器,我已经订阅了 shoppingCart
像这样
output?.shoppingCart
.map {
print("Mapping")
return [=12=].lines.count == 0
}
.asObservable()
.bind(to: goToCartButton.rx.isHidden)
.disposed(by: bag)
我放置 print("Mapping")
是为了意识到在执行修改我的模型并触发我之前提到的 Observable<ShoppingCart>
的操作后,最后一个驱动程序会不断被触发。
我哪里做错了?
感谢您的帮助。
要停止订阅观察者必须执行以下操作之一:
发送错误信息
发送完成的消息
销毁订阅(销毁disposeBag)
在你的情况下 rx.viewWillAppear
也不会 shoppingCart
不发送错误或完成的消息,因为它们是驱动程序
您正确停止订阅的一种方法是销毁旧的 disposeBag
bag = DisposeBag()
但不要忘记在 viewWillAppear 上恢复订阅
其他选项 将在 VC 中有一些标志,例如
var hasAppeared: Bool
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
...
hasAppeared = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisppear(animated)
...
hasAppeared = false
}
并且只是为了添加过滤
output?.shoppingCart
.filter({ [weak self] _ in self?.hasAppeared ?? false })
.map {
print("Mapping")
return [=11=].lines.count == 0
}
.asObservable()
.bind(to: goToCartButton.rx.isHidden)
.disposed(by: bag)
第三种方式是停止从viewModel内部发送
let initTrigger = rx.viewWillAppear
.mapToVoid()
.asDriverOnErrorJustComplete()
let stopTrigger = rx.viewWillDisappear
.mapToVoid()
.asDriverOnErrorJustComplete()
let shoppingCart: Driver<ShoppingCart>
let shoppingCart = Observable.merge(input.initTrigger.map({ true }),
input.stopTrigger.map({ false }))
.flatMapLatest { isRunning in
guard isRunning else {
return .just(ShoppingCart())
}
return self.getShoppingCartUseCase
.execute()
.asDriver(onErrorJustReturn: ShoppingCart())
}
首先你可以使用.distincUntilChanged()
来过滤相同的事件。
其次,检查为什么 .getShoppingCartUseCase
不断发出事件,只要 ShoppingCart 被写入数据库,RxRealm 就会发送更新,所以也许你有一些不必要的写入。确保当你写入领域时使用 .modified
标志,而不是 .all
(只有当项目发生变化时才会覆盖它,如果没有变化则不会引起事件)
如果您确定只需要参加一次活动 - 您可以随时添加 .take(1)
你也称它为 initTrigger
,但在 viewWillAppear
上发送它——当你返回屏幕时可以调用它多次。如果你需要一次,把它放在viewDidLoad
PS 而不是 .asObservable().bind(to:...)
你可以只写 .drive(...)
这是将驱动程序绑定到 ui.