Swift 在视图模型和视图控制器之间不断触发驱动程序
RxSwift上的Swift 在视图模型和视图控制器之间不断触发驱动程序,swift,realm,rx-swift,rx-cocoa,Swift,Realm,Rx Swift,Rx Cocoa,RxSwift上的驱动程序出现问题。让一个视图模型监听ViewController中的initTrigger,如下所示 let initTrigger = rx.viewWillAppear .mapToVoid() .asDriverOnErrorJustComplete() 此initTrigger用于绑定到视图模型上的另一个Driver let shoppingCart: Driver<Shoppin
驱动程序出现问题。让一个视图模型监听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())
}
我放置了print(“Mapping”)
,以意识到最后一个驱动程序在做出修改我的模型并触发我前面提到的Observable
的操作后不断被触发
我做错了什么
感谢您的帮助。要停止订阅,必须执行以下操作之一:
发送错误消息
发送完成的消息
处置订阅(销毁处置包)
在您的情况下,norrx.view将出现shoppingCart
都不会发送错误或已完成的消息,因为它们是驱动程序
正确停止订阅的一种方法是销毁旧的disposeBag
bag=DisposeBag()
但别忘了在视图上恢复订阅
另一个选项是在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 $0.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())
}
让initTrigger=rx.viewwill出现
.maptovid()
.asDriverOnErrorJustComplete()文件
让stopTrigger=rx.viewwill消失
.maptovid()
.asDriverOnErrorJustComplete()文件
让购物车:司机
让shoppingCart=Observable.merge(input.initTrigger.map({true}),
input.stopTrigger.map({false}))
.flatMapLatest{正在运行中
卫兵在跑别的东西{
return.just(ShoppingCart())
}
return self.getShoppingCartUseCase
.execute()
.asDriver(onErrorJustReturn:ShoppingCart())
}
首先,您可以使用.distincontilchanged()
过滤相同的事件。
其次,检查为什么.getShoppingCartUseCase
不断发出事件,RxRealm将在ShoppingCart写入db时发送更新,因此可能您有一些不必要的写入。确保在写入域时使用的是.modified
标志,而不是.all
(只有在项目发生更改时才会覆盖该项目,如果项目没有更改,则不会引发事件)
如果您确定只需添加一次事件,则始终可以添加。采取(1)
您也可以将其称为initTrigger
,但将其发送到viewwillbeen
——返回屏幕时可以多次调用它。如果您需要一次,请将其置于viewDidLoad
PS而不是.asObservable().bind(to:…)
您可以只编写.drive(…)
,这是将驱动程序绑定到ui的更干净的方法。我明白了,但我对这种方法有一个问题,我正试图遵循RxSwift MVVM模式,这样我的viewModel就有一个输入,带有rx.viewwillbelook
和一个输出shoppingCart
,我有一个转换方法来连接它们。我在viewDidLoad上调用了这个方法,所以我不能使用hassemerged
方法。还有另一种方法可以摧毁旧的处置包?这是第二种选择。第一种方法是使用bag=DisposeBag()
在viewwilldiscover
上销毁dispose bag,然后在viewwillbeen上重新订阅Yes,问题是由于未使用take(1)
造成的。在更新模型之前将其添加到正在使用的领域查询中之后,一切都按预期进行。非常感谢你。另外,感谢您关于使用.drive(…)
的建议。很高兴我提供了帮助,但请注意,添加take(1)可能是症状修复,而不是实际的错误修复。试着去了解,为什么你的领域可以观测到发射事件,也许是有不必要的写入器去dbI找到了原因。使用可观测的方法是使用信号进行一些更改并再次保存相同的模型,再次触发可观测并创建无限循环。在这种情况下,take(1)是实际的bug修复。
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())
}