【问题标题】:How to combine two results from the different subjects and use latest one's result如何结合来自不同学科的两个结果并使用最新的结果
【发布时间】:2022-01-22 02:19:55
【问题描述】:

我有两个视图模型。一个用于单个联系人管理,另一个用于整个联系人列表管理。

而且我有可能发生的两个错误。在这两种情况下,我都应该应用相同的操作 - 以显示错误。但是我该如何更优雅地做到这一点,以便每次,无论来自哪个视图模型错误,都只根据最后一个错误来显示它?

我现在有这个代码:

 private func observeErrors(){
        
        let popup = PopupViewController.instantiate()
        let popupActionHandler =  {
            popup.dismiss(animated: true, completion: nil)
        }
        
        contactsViewModel.error.subscribe(onNext: { error in
            print(error.localizedDescription)
            switch error {
        
            case .unknown:
                self.showPopup(popup: popup, popupTitle: "An unknown error occured".localized, popupMessage: "Please try again.".localized, buttonTitle: nil, actionHandler: popupActionHandler)
            case .serverResponse(let message):
                
                self.showPopup(popup: popup, popupTitle: "An error occured".localized, popupMessage: message, buttonTitle: nil, actionHandler: popupActionHandler)
                
            }
        }).disposed(by: disposeBag)
        
        contactViewModel.error.subscribe(onNext: { error in
            print(error.localizedDescription)
            switch error {
           
            case .unknown:
                self.showPopup(popup: popup, popupTitle: "An unknown error occured".localized, popupMessage: "Please try again.".localized, buttonTitle: nil, actionHandler: popupActionHandler)
            case .serverResponse(let message):
                
                self.showPopup(popup: popup, popupTitle: "An error occured".localized, popupMessage: message, buttonTitle: nil, actionHandler: popupActionHandler)
                
            }
        }).disposed(by: disposeBag)
    }

但这是重复的。我尝试使用combineLatest,但我不确定如何确定发生的最后一个错误是什么并只显示它?

【问题讨论】:

    标签: ios swift rx-swift rx-cocoa


    【解决方案1】:

    就我而言,有两种方法, 第一,

    private func observeErrors(){
        
        let popup = PopupViewController.instantiate()
        let popupActionHandler =  {
            popup.dismiss(animated: true, completion: nil)
        }
        var contactVM = (contactsViewModel!= null)? contactsViewModel : contactViewModel
        contactVM.error.subscribe(onNext: { error in
            print(error.localizedDescription)
            switch error {
        
            case .unknown:
                self.showPopup(popup: popup, popupTitle: "An unknown error occured".localized, popupMessage: "Please try again.".localized, buttonTitle: nil, actionHandler: popupActionHandler)
            case .serverResponse(let message):
                
                self.showPopup(popup: popup, popupTitle: "An error occured".localized, popupMessage: message, buttonTitle: nil, actionHandler: popupActionHandler)
                
            }
        }).disposed(by: disposeBag)
    }
    

    第二种方式,使用泛型。

    注意:我是 iOS 开发人员。我是熟练的 Objective-C 开发人员,我在 swift 语法方面没有太多经验,所以我的书面回答可能是错误语法的机会

    【讨论】:

    • 这永远不会显示contactViewModel 错误,因为contactsViewModel 永远不会为零。
    【解决方案2】:

    我猜你可以使用

    Observable.merge
    

    因此它需要 n 个可观察对象(必须具有相同的元素类型)并将单个订阅者附加到两者。它们合并为一个流:

    Observable.merge(contactsViewModel.error, contactViewModel.error)
        .subscribe(onNext: { error in 
            // your logic for both observables
        })
        .disposed(by: disposeBag)
    

    【讨论】:

    • 正确答案。我还会在将错误转换为(title: String, message: String) 的订阅之前添加map。您希望订阅的onNext 中的代码尽可能少,因为该代码不可测试。
    • @DanielT。感谢您的提示!
    【解决方案3】:

    @RicoCrescenzio 是正确的;使用Observable.merge。也就是说,您发表了关于仅显示“最后一个”错误的评论。我假设你的意思是最近的。例如,如果在显示弹出窗口时其中一个可观察对象发出错误,那么您想要关闭当前弹出窗口并显示新的弹出窗口(即使用户没有点击按钮。)这样做有点多复杂而坦率地说可能没有必要,但我不知道您的用例的详细信息。

    为了更容易,我使用了我的CLE library。当任一错误可观察对象发出值时,下面的代码将显示带有标题和消息的 UIAlertController。如果当前正在显示来自先前错误的警报,它将在显示新错误之前关闭该警报。

    // only call this once in viewDidLoad
    private func observeErrors() {
        Observable.merge(contactsViewModel.error, contactViewModel.error)
            .map { (error) -> (title: String, message: String) in
                switch error {
                case .unknown:
                    return (title: "An unknown error occured".localized, message: "Please try again.".localized)
                case let .serverResponse(message):
                    return (title: "An error occured".localized, message: message)
                }
            }
            .flatMapLatest(presentScene(animated: true, scene: { title, message in
                UIAlertController(title: title, message: message, preferredStyle: .alert)
                    .scene { $0.connectOK() }
            }))
            .subscribe()
            .disposed(by: disposeBag)
    }
    

    【讨论】:

    • 是的,目前在弹出弹出窗口时不会发生错误,但肯定是应该考虑的情况。谢谢你的例子!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 2020-03-25
    相关资源
    最近更新 更多