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 来拯救的典型场景。你必须有某种共享容器,它将 register
和 resolve
依赖。我使用Dip
https://github.com/AliSoftware/Dip.git,这是您的代码示例。想法如下 - 您在一个 VC 中注册闭包并将其传递给另一个。
【讨论】:
以上是关于MVVM + RXSwift+ Coordinator 如何设置数据?的主要内容,如果未能解决你的问题,请参考以下文章
MVVM + RXSwift+ Coordinator 如何设置数据?
RxSwift 和 MVVM:observable 在没有绑定的情况下无法执行