【问题标题】:RxSwift concurrency problems with coordinator协调器的 RxSwift 并发问题
【发布时间】:2021-04-13 12:36:26
【问题描述】:

我想做的事

  1. 介绍 VC1
  2. 当 VC1 关闭时,显示 VC2

问题

  1. 当 VC1 关闭时,VC2 不存在

脏修复: 放毫秒延迟。它解决了问题,但想知道它为什么会发生

说明:当 VC1 关闭时,我得到 viewDidDissapear 事件,因此我可以呈现 VC2

如果您需要更多详细信息,请询问。

代码

class ViewModel {

    let coordinator = Coordinator()

    struct Input {
        let itemSelected: Driver<IndexPath>
    }

    struct Output {
        let presentVC1: Driver<Void>
        let presentVC2: Driver<Void>
    }

    func transform(input: Input) -> Output {

        let navigateToVC1 = input.itemSelected
            .flatMap { [coordinator] in
                return coordinator.transition(to: Scene.VC1)
            }

        let navigateToVC2 = navigateToVC1
            .delay(.milliseconds(1))
            .flatMap { [coordinator] in
                return coordinator.transition(to: Scene.VC2)
            }

        return Output(presentVC1: presentVC1, presentVC2: presentVC2)
    }

协调员代码:

func transition(to scene: TargetScene) -> Driver<Void> {
        let subject = PublishSubject<Void>()

        switch scene.transition {
           
            case let .present(viewController):
                _ = viewController.rx
                    .sentMessage(#selector(UIViewController.viewDidDisappear(_:)))
                    .map { _ in } 
                    .bind(to:subject)
                currentViewController.present(viewController, animated: true)
                
        return subject
            .take(1)
            .asDriverOnErrorJustComplete()
    }

【问题讨论】:

    标签: ios swift rx-swift rx-cocoa


    【解决方案1】:

    在视图控制器完全关闭之前调用viewDidDisappear 方法。在调用dismiss 的回调之前,您不应尝试呈现第二个视图控制器。

    无论您在何处关闭视图控制器,请改用以下内容,并且在 observable 发出下一个事件之前不要显示下一个视图控制器。

    extension Reactive where Base: UIViewController {
        func dismiss(animated: Bool) -> Observable<Void> {
            Observable.create { [base] observer in
                base.dismiss(animated: animated) {
                    observer.onNext(())
                    observer.onCompleted()
                }
                return Disposables.create()
            }
        }
    }
    

    我建议您考虑使用我的 Cause-Logic-Effect 架构,其中包含正确处理视图控制器呈现和关闭所需的一切。

    https://github.com/danielt1263/CLE-Architecture-Tools

    部分界面如下:

    /**
    Presents a scene onto the top view controller of the presentation stack. The scene will be dismissed when either the action observable completes/errors or is disposed.
    - Parameters:
    - animated: Pass `true` to animate the presentation; otherwise, pass `false`.
    - sourceView: If the scene will be presented in a popover controller, this is the view that will serve as the focus.
    - scene: A factory function for creating the Scene.
    - Returns: The Scene's output action `Observable`.
    */
    func presentScene<Action>(animated: Bool, overSourceView sourceView: UIView? = nil, scene: @escaping () -> Scene<Action>) -> Observable<Action>
    
    extension NSObjectProtocol where Self : UIViewController {
    
        /**
            Create a scene from an already existing view controller.
        
            - Parameter connect: A function describing how the view controller should be connected and returning an Observable that emits any data the scene needs to communicate to its parent.
            - Returns: A Scene containing the view controller and return value of the connect function.
        
            Example:
        
            `let exampleScene = ExampleViewController().scene { $0.connect() }`
            */
        func scene<Action>(_ connect: (Self) -> Observable<Action>) -> Scene<Action>
    }
    
    struct Scene<Action> {
        let controller: UIViewController
        let action: Observable<Action>
    }
    

    connect 函数是你的视图模型,当它的 Observable 完成或它的订阅者释放时,视图控制器将自动关闭。

    presentScene 函数是您的协调器。它处理场景的实际呈现和解除。当您关闭并呈现一个新场景时,它将正确处理等待,直到前一个视图控制器被关闭后再呈现下一个。

    【讨论】:

    • 感谢 Daniel T. 的帮助。欣赏它。
    猜你喜欢
    • 2019-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多