MVVM + RXSwift+ Coordinator 如何设置数据?

Posted

技术标签:

【中文标题】MVVM + RXSwift+ Coordinator 如何设置数据?【英文标题】:MVVM + RXSwift+ Coordinator how to set data? 【发布时间】:2022-01-24 02:14:27 【问题描述】:

晚安! 你能告诉我如何将数据从控制器 2 写入控制器 1 吗? 我在主屏幕上有一个坐标。

final class MenuCoffeLikeCoordinator: TabBarPresentableCoordinator 

var tabBarItem: UITabBarItem = 
    let title = "Меню"
    let image = UIImage(asset: Resources.Assets.TabBarItems.mainTabBar)
    let selectedImage = UIImage(asset: Resources.Assets.TabBarItems.mainTabBarSelected)
    let item = UITabBarItem(title: title, image: image, selectedImage: selectedImage)
    return item
()

var navigationController: UINavigationController

init(navigationController: UINavigationController = UINavigationController()) 
    self.navigationController = navigationController


var didFinish: (() -> Void)?

func start() 
    self.navigationController.pushViewController(createMenuCoffeLikeFlow(), animated: true)


func stop() 

func createMenuCoffeLikeFlow()  -> UIViewController 
    let menuController = MenuCoffeLikeAssembler.createModule()
    
    menuController.rx.didTapMapLayer.onNext 
        let controller = self.createCoffeeBarMap()
        self.navigationController.pushViewController(controller, animated: true)
    
    
    return menuController

private func createCoffeeBarMap() -> UIViewController 
    let controller = CoffeeBarContainerAssembler.createModule()
    controller.obsRelay.subscribe(onNext:  event in
        self.navigationController.popViewController(animated: true)
    )
    return controller

在 createMenuCoffeeLikeFlow 函数中,我创建了主屏幕,当我点击按钮时,我转到屏幕 2 (createCoffeeBarMap)

在函数(createCoffeeBarMap)内部,我订阅了PublishSubject,当数据发生变化时,我得到一个新的文本。 我需要在 createMenuCoffeeLikeFlow 函数中的 menuCoffeeControler 中编写此文本。我该怎么做?

【问题讨论】:

你从哪里得到这个架构?他们对如何将数据传回之前的控制器有什么看法? @DanielT。这是 mvvm。 不,不是。至少不是我见过的任何 MVVM。你在哪里找到像这样的代码? @DanielT。它唯一的协调员,也许我没有那样实现它,如果有一个例子我会很感激 【参考方案1】:

以下是我将如何使用我的 Cause Logic Effect (CLE) 架构来实现它。使用 CLE,您不需要实现 Coordinator,因为库中已经存在可重用的 Coordinator 类。这意味着您可以编写更少的代码。

与您的不同,此示例是完整的并且可以编译。唯一缺少的是视图控制器内视图的创建和布局。

import Cause_Logic_Effect
import RxCocoa
import RxSwift
import UIKit

/// This function produces the view controller that is attached to your tab bar controller. I don't put the
/// `UITabBarItem` in here. Instead I attach that when connecting to the tab bar controller.
func menuCoffeLikeTab() -> UIViewController 
    // the `configure` function calls its closure inside the viewDidLoad method.
    let menuController = MenuController().configure  $0.connect() 
    let controller = UINavigationController(rootViewController: menuController)
    return controller


/// It depends on how you want to layout your view controllers on whether anything else goes in here. If you
/// use storyboards, then add `@IBOutlet` before the views here. If you create your views programatically
/// then add a `loadView()` override.
final class MenuController: UIViewController 
    var mapLayerButton: UIButton!
    var textField: UITextField!
    let disposeBag = DisposeBag()


extension MenuController 
    func connect() 
        // This is the meat. The `coffeeBarResponse` observable pushes the
        // CoffeeBarController onto the navigation stack when approprate and
        // then emits any values produced by it. Notice how this looks alot like
        // a network call except you are querying the user instead of the server.
        let coffeeBarResponse = mapLayerButton.rx.tap
            .flatMapFirst(pushScene(on: navigationController!, animated: true) 
                CoffeeBarController().scene  $0.connect() 
            )
            .share()
        // The pushScene function above will create a coordinator for the
        // CoffeeBarController. When needed, the coordinator will create the
        // view controller, call its `connect` and emit any values from that.
        // When the Observable completes, the coordinator will pop the view
        // controller off.

        coffeeBarResponse
            .bind(to: textField.rx.text)
            .disposed(by: disposeBag)
    


final class CoffeeBarController: UIViewController 
    var saveButton: UIButton!
    var textField: UITextField!


extension CoffeeBarController 
    func connect() -> Observable<String> 
        // when the user taps the save button, this will emit whatever value is
        // in the text field and then complete the observable.
        saveButton.rx.tap
            .withLatestFrom(textField.rx.text.orEmpty)
            .take(1)
    

就像我上面所说的,这使用了一个可重用的 Coordinator 类,它是库的一部分,而不是你必须一直编写自己的。这种架构将显着减少您必须编写的样板代码量。在https://github.com/danielt1263/CLE-Architecture-Tools 了解更多信息并加入 RxSwift Slack 以了解更多关于 RxSwift 的一般信息。

【讨论】:

【参考方案2】:

这是 DI 来拯救的典型场景。你必须有某种共享容器,它将 registerresolve 依赖。我使用Diphttps://github.com/AliSoftware/Dip.git,这是您的代码示例。想法如下 - 您在一个 VC 中注册闭包并将其传递给另一个。

【讨论】:

以上是关于MVVM + RXSwift+ Coordinator 如何设置数据?的主要内容,如果未能解决你的问题,请参考以下文章

MVVM + RXSwift+ Coordinator 如何设置数据?

RxSwift(24)——MVVM双向绑定

用于搜索屏幕的 MVVM 和 RxSwift

RxSwift 和 MVVM:observable 在没有绑定的情况下无法执行

如何使用 MVVM 和 RxSwift 编辑/删除 UICollectionView 单元格

RxSwift MVVM 实现查询