RxSwift:从没有主题

时间:2017-02-17 11:21:01

标签: swift reactive-programming rx-swift rx-cocoa

我的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
}

3 个答案:

答案 0 :(得分:4)

由于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" }
  }
}

答案 1 :(得分:0)

如果有人需要rx属性,这里是一个受@ marco-santarossa代码启发的现成解决方案

extension Reactive where Base: UIView {
    var willMoveToWindow: Observable<Bool> {
        return self.sentMessage(#selector(Base.willMove(toWindow:)))
            .map({ $0.filter({ !($0 is NSNull) }) })
            .map({ $0.isEmpty == false })
    }
    var viewWillAppear: Observable<Void> {
        return self.willMoveToWindow
            .filter({ $0 })
            .map({ _ in Void() })
    }
    var viewWillDisappear: Observable<Void> {
        return self.willMoveToWindow
            .filter({ !$0 })
            .map({ _ in Void() })
    }
}

答案 2 :(得分:0)

let viewDidAppear = rx.sentMessage(#selector(UIViewController.viewDidAppear(_:)))
        .mapToVoid()
        .asDriver(onErrorJustReturn: ())