gpt4 book ai didi

ios - 如何使用MVVM和RxSwift事件在UIViewController及其子UIView之间进行通信?

转载 作者:行者123 更新时间:2023-12-01 16:07:37 24 4
gpt4 key购买 nike

我在项目中使用MVVM,Clean Architecture和RxSwift。有一个 View Controller 具有一个子UIView,该子UIView是由一个单独的.xib文件动态创建的(因为它在多个场景中使用)。因此,有两个 View 模型,即UIViewController的 View 模型和UIView的 View 模型。现在,子级 View 模型中有一个Rx事件,父级应观察到该事件,然后它将调用其某些 View 模型的功能。代码是这样的:

MyPlayerViewModel:

class MyPlayerViewModel: UIView {
var eventShowUp: PublishSubject<Void> = PublishSubject<Void>()
var rxEventShowUp: Observable<Void> {
return eventShowUp
}
}

MyPlayerView:
class MyPlayerView: UIView {
var viewModel: MyPlayerViewModel?

setup(viewModel: MyPlayerViewModel) {
self.viewModel = viewModel
}
}

MyPlayerSceneViewController:
class MyPlayerSceneViewController: UIViewController {
@IBOutlet weak var myPlayerView: MyPlayerView!
@IBOutlet weak var otherView: UIView!

var viewModel: MyPlayerSceneViewModel
fileprivate var disposeBag : DisposeBag = DisposeBag()

override func viewDidLoad() {
super.viewDidLoad()
self.myPlayerView.viewModel.rxEventShowUp.subscribe(onNext: { [weak self] in
self?.viewModel.doOnShowUp()
self?.otherView.isHidden = true
})
}
}

如您所见,目前,我正在向公众公开myPlayerView的viewModel,以便父级可以观察其事件。这是正确的方法吗?如果没有,关于更好的方法还有其他建议吗?谢谢。

最佳答案

通常,将 View 的内容公开给其 View Controller 没有什么不好,但是您真的需要在那里使用两个单独的 View 模型吗?您是否不将viewModel和模型职责混合在一起?

一些想法:

  • 模型不应继承UIView
  • 您应该避免在 View 模型中创建自己的主题。它不会自行创建事件,它仅处理输入并公开结果。
  • 我鼓励您熟悉BinderDriver

  • 这是代码示例:
    struct PlayerModel {

    let id: Int
    let name: String
    }

    class MyPlayerSceneViewModel {

    struct Input {
    let eventShowUpTrigger: Observable<Void>
    }

    struct Output {
    let someUIAction: Driver<PlayerModel>
    }

    func transform(input: Input) -> Output {
    let someUIAction = input.eventShowUpTrigger
    .flatMapLatest(fetchPlayerDetails) // Transform input
    .asDriver(onErrorJustReturn: PlayerModel(id: -1, name: "unknown"))

    return Output(someUIAction: someUIAction)
    }

    private func fetchPlayerDetails() -> Observable<PlayerModel> {
    return Observable.just(PlayerModel(id: 1, name: "John"))
    }
    }

    class MyPlayerView: UIView {

    var eventShowUp: Observable<Void> {
    return Observable.just(()) // Expose some UI trigger
    }

    var playerBinding: Binder<PlayerModel> {
    return Binder(self) { target, player in
    target.playerNameLabel.text = player.name
    }
    }

    let playerNameLabel = UILabel()
    }

    class MyPlayerSceneViewController: UIViewController {

    @IBOutlet weak var myPlayerView: MyPlayerView!

    private var viewModel: MyPlayerSceneViewModel!
    private var disposeBag: DisposeBag = DisposeBag()

    override func viewDidLoad() {
    super.viewDidLoad()
    setupBindings()
    }

    private func setupBindings() {
    let input = MyPlayerSceneViewModel.Input(eventShowUpTrigger: myPlayerView.eventShowUp)
    let output = viewModel.transform(input: input)

    // Drive manually
    output
    .someUIAction
    .map { $0.name }
    .drive(myPlayerView.playerNameLabel.rx.text)
    .disposed(by: disposeBag)

    // or to exposed binder
    output
    .someUIAction
    .drive(myPlayerView.playerBinding)
    .disposed(by: disposeBag)
    }
    }

    关于ios - 如何使用MVVM和RxSwift事件在UIViewController及其子UIView之间进行通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54361755/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com