Search code examples
swiftmvvmrx-swiftdrivebehaviorrelay

RxSwift modelSelected Drive model on model View & Get that model on DetailView


This is my FirstView ( Parent VIew)

tableView.rx.modelSelected(Kinder.self)
        .asDriver()
        .drive(self.detailKinderViewModel.currentKinder)
        .disposed(by: disposeBag)

This is ViewModel ( BehaviorRelay )

    lazy var currentKinder = BehaviorRelay<Kinder>(value: Kinder())

This is My SecondView ( Child View )

override func viewDidLoad() {
    super.viewDidLoad()
    detailKinderViewModel.currentKinder
        .asDriver(onErrorJustReturn:Kinder())
        .map{$0.kinder_name}
        .drive(self.navigationItem.rx.title)
        .disposed(by: disposeBag)
}

I can get Only Default Model Data.

I want to Get current Data on Child View


Solution

  • There isn't enough code to figure out what your problem might be. Here is how I would do it using my Cause_Logic_Effect library.

    import Cause_Logic_Effect
    import RxCocoa
    import RxSwift
    import UIKit
    
    extension FirstView {
        func connect() {
            Observable.just([
                Kinder(name: "Ben"),
                Kinder(name: "Mia"),
                Kinder(name: "Leon"),
                Kinder(name: "Emma")
            ])
                .bind(to: tableView.rx.items(cellIdentifier: "Cell")) { _, kinder, cell in
                    if #available(iOS 14.0, *) {
                        var configuration = cell.defaultContentConfiguration()
                        configuration.text = kinder.name
                        cell.contentConfiguration = configuration
                    }
                    else {
                        cell.textLabel?.text = kinder.name
                    }
                }
                .disposed(by: disposeBag)
            
            // when the user selects a cell, load its Kinder into a newly created
            // SecondView and push it onto the navigation stack
            tableView.rx.modelSelected(Kinder.self)
                .bind(onNext: pushScene(on: navigationController!, animated: true) { kinder in
                    SecondView().scene { $0.connect(kinder: kinder) }
                })
                .disposed(by: disposeBag)
        }
    }
    
    extension SecondView {
        func connect(kinder: Kinder) -> Observable<Never> {
            // use the Kinder
            title = kinder.name
            
            // this controller doesn't send any info back to its parent.
            return .never()
        }
    }
    
    // The view controllers.
    final class FirstView: UIViewController {
        var tableView: UITableView!
        let disposeBag = DisposeBag()
        
        override func loadView() {
            super.loadView()
            title = "Main"
            tableView = UITableView(frame: view.bounds)
            tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
            tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
            view.addSubview(tableView)
        }
    }
    
    final class SecondView: UIViewController {
        override func loadView() {
            super.loadView()
            view.backgroundColor = .white
        }
    }
    
    // The models
    struct Kinder {
        let name: String
    }
    
    @main
    class AppDelegate: UIResponder, UIApplicationDelegate {
        
        var window: UIWindow?
        
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            
            window = UIWindow(frame: UIScreen.main.bounds)
            // Create a FirstView, configure it with a connector, wrap it in a
            // navigation controller and make that the root.
            window?.rootViewController = UINavigationController(rootViewController: FirstView().configure { $0.connect() })
            window?.makeKeyAndVisible()
    
            return true
        }
    }