如何结合不同科目的两个结果并使用最新的结果

How to combine two results from the different subjects and use latest one's result

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

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

我现在有这个代码:

 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,但我不确定如何确定最后发生的错误是什么并仅显示该错误?

我有两种方法, 第一,

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 语法方面没有太多经验,所以我的书面回答可能是语法错误的机会

我想你可以使用

Observable.merge

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

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

@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 { [=10=].connectOK() }
        }))
        .subscribe()
        .disposed(by: disposeBag)
}