RxSwift:从没有主题的视图模型观察 viewDidLoad
RxSwift: Observe viewDidLoad from view model without Subjects
我的 UIViewController
和我的视图模型存在依赖性问题。
基本上我想在我的视图模型中收听 viewDidLoad
事件。
目前我有一个 Class A
实例化视图模型和 UIViewController
参数 viewModel,所以:
let viewModel = ViewModel()
let viewController = UIViewController(viewModel)
并且我已经为 viewDidLoad
:
创建了一个 RxCocoa 扩展
var viewDidLoad: Observable<Void> {
return self.sentMessage(#selector(Base.viewDidLoad)).map { _ in Void() }
}
现在我不得不将此 rx.viewDidLoad
绑定到我的视图模型中的一个可观察对象。我可以使用 Subjects
来完成,但我想要一种仅使用 Observable
的反应式方法。
我知道我可以注入 rx.viewDidLoad
作为视图模型的构造函数参数,但这样我会破坏我的体系结构,我不想让 UIViewController
在内部实例化视图模型,但我想将其保留为注入的依赖项。
有什么建议吗?
谢谢
解决方案
感谢@tomahh 我使用了这个解决方案:
我的视图控制器:
override func configure(viewModel: ViewModel) {
viewModel.bindViewDidLoad(rx.viewDidLoad)
}
我的视图模型:
func bindViewDidLoad(_ viewControllerDidLoad: Observable<Void>) {
//Create observers which depend on viewControllerDidLoad
}
因为ViewController
已经知道视图模型,它可以在初始化时ViewModel
上设置一个属性
class ViewController: UIViewController {
init(_ viewModel: ViewModel) {
viewModel.viewDidLoad = self.rx.viewDidLoad
}
}
然后,ViewModel
中的可观察值可以定义为计算 属性 推导 viewDidLoad
struct ViewModel {
var viewDidLoad: Observable<Void> = .never()
var something: Observable<String> {
return viewDidLoad.map { "Huhu, something is guuut" }
}
}
如果有人需要 rx 属性,这里是一个随时可用的解决方案,灵感来自@marco-santarossa
extension Reactive where Base: UIView {
var willMoveToWindow: Observable<Bool> {
return self.sentMessage(#selector(Base.willMove(toWindow:)))
.map({ [=10=].filter({ !([=10=] is NSNull) }) })
.map({ [=10=].isEmpty == false })
}
var viewWillAppear: Observable<Void> {
return self.willMoveToWindow
.filter({ [=10=] })
.map({ _ in Void() })
}
var viewWillDisappear: Observable<Void> {
return self.willMoveToWindow
.filter({ ![=10=] })
.map({ _ in Void() })
}
}
let viewDidAppear = rx.sentMessage(#selector(UIViewController.viewDidAppear(_:)))
.mapToVoid()
.asDriver(onErrorJustReturn: ())
我的 UIViewController
和我的视图模型存在依赖性问题。
基本上我想在我的视图模型中收听 viewDidLoad
事件。
目前我有一个 Class A
实例化视图模型和 UIViewController
参数 viewModel,所以:
let viewModel = ViewModel()
let viewController = UIViewController(viewModel)
并且我已经为 viewDidLoad
:
var viewDidLoad: Observable<Void> {
return self.sentMessage(#selector(Base.viewDidLoad)).map { _ in Void() }
}
现在我不得不将此 rx.viewDidLoad
绑定到我的视图模型中的一个可观察对象。我可以使用 Subjects
来完成,但我想要一种仅使用 Observable
的反应式方法。
我知道我可以注入 rx.viewDidLoad
作为视图模型的构造函数参数,但这样我会破坏我的体系结构,我不想让 UIViewController
在内部实例化视图模型,但我想将其保留为注入的依赖项。
有什么建议吗? 谢谢
解决方案
感谢@tomahh 我使用了这个解决方案:
我的视图控制器:
override func configure(viewModel: ViewModel) {
viewModel.bindViewDidLoad(rx.viewDidLoad)
}
我的视图模型:
func bindViewDidLoad(_ viewControllerDidLoad: Observable<Void>) {
//Create observers which depend on viewControllerDidLoad
}
因为ViewController
已经知道视图模型,它可以在初始化时ViewModel
上设置一个属性
class ViewController: UIViewController {
init(_ viewModel: ViewModel) {
viewModel.viewDidLoad = self.rx.viewDidLoad
}
}
然后,ViewModel
中的可观察值可以定义为计算 属性 推导 viewDidLoad
struct ViewModel {
var viewDidLoad: Observable<Void> = .never()
var something: Observable<String> {
return viewDidLoad.map { "Huhu, something is guuut" }
}
}
如果有人需要 rx 属性,这里是一个随时可用的解决方案,灵感来自@marco-santarossa
extension Reactive where Base: UIView {
var willMoveToWindow: Observable<Bool> {
return self.sentMessage(#selector(Base.willMove(toWindow:)))
.map({ [=10=].filter({ !([=10=] is NSNull) }) })
.map({ [=10=].isEmpty == false })
}
var viewWillAppear: Observable<Void> {
return self.willMoveToWindow
.filter({ [=10=] })
.map({ _ in Void() })
}
var viewWillDisappear: Observable<Void> {
return self.willMoveToWindow
.filter({ ![=10=] })
.map({ _ in Void() })
}
}
let viewDidAppear = rx.sentMessage(#selector(UIViewController.viewDidAppear(_:)))
.mapToVoid()
.asDriver(onErrorJustReturn: ())