【问题标题】:How do I perform either a push UIViewController or a present of UIAlertController?如何执行推送 UIViewController 或呈现 UIAlertController?
【发布时间】:2019-05-27 02:08:13
【问题描述】:

在一些 API 调用之后,我可以检查是否导航到另一个屏幕或在同一屏幕上显示警报。目前,我通过创建一个返回 UIViewController 类型但推送 UIAlertController 会导致问题的 observable 来做到这一点。

关于如何做到这一点的任何建议/想法?

ViewModel.swift

let nextAction = Observable.combineLatest(appVersionOutput, serviceAvailabilityOutput, getLanguagePackOutput,
                                              resultSelector:
        { appVersion, _, _ -> UIViewController in
            if appVersion.currentAppVersion == "1.0.0" {
                let appServiceAvailability = Availability.shared.getAppStatus()
                if appServiceAvailability {
                    return LoginLandingViewController()
                } else {
                    return ServiceMaintenanceViewController()
                }
            } else {
                return UIAlertController()
            }
        })

ViewController.swift

viewModel.output.nextAction
        .subscribe(onNext: { [weak self] screen in
            self?.navigationController?.pushViewController(screen, animated: true) 
        }) // PROBLEM FACED: Pushing a UIAlertController
        .disposed(by: disposeBag)

【问题讨论】:

  • 据我了解最好返回错误,并根据错误状态显示视图控制器或警报。

标签: swift mvvm uiviewcontroller uialertcontroller rx-swift


【解决方案1】:

您可以使用 classForCoder

检查课程
viewModel.output.nextAction
    .subscribe(onNext: { [weak self] screen in
        if String(describing: screen.classForCoder) == "UIAlertController" {
            //present
            self?.present(screen, animated: true, completion: nil)
        } else {
            //navigate
            self?.navigationController?.pushViewController(screen, animated: true)
        } 
    }) // PROBLEM FACED: Pushing a UIAlertController
    .disposed(by: disposeBag)

【讨论】:

    【解决方案2】:

    有几个选项。

    第一个选项是采用您当前的实现。 除了 ViewController 之外,您还可以在 nextAction observable 的 onNext 事件中传递一个信息,这将告诉如何显示 VC。

    例如,您可以创建关联的枚举

    // you can call it NextAction, Action etc
    enum PresentationType {
        case
        push(UIViewController),
        present(UIViewController)
    }
    

    并像这样重复使用它:

    let nextAction = Observable.combineLatest(appVersionOutput, serviceAvailabilityOutput, getLanguagePackOutput,
                                              resultSelector:
        { appVersion, _, _ -> PresentationType in
            if appVersion.currentAppVersion == "1.0.0" {
                let appServiceAvailability = Availability.shared.getAppStatus()
                if appServiceAvailability {
                    return .push(LoginLandingViewController())
                } else {
                    return .push(ServiceMaintenanceViewController()) // use .present if should present modally
                }
            } else {
                return .present(UIAlertController())
            }
    })
    
    // somewhere in viewController
    
    viewModel.output.nextAction
            .subscribe(onNext: { [weak self] action in
            switch action {
                case .push(let vc):
                    self?.navigationController?.pushViewController(vc, animated: true)
                case .present(let vc):
                    self?.present(vc, animated: true, completion: nil)
    
            })
            .disposed(by: disposeBag)
    

    第二个(在某种意义上更灵活和可测试)选项是创建一个单独的路由器类,该类负责创建和显示下一个屏幕(具有函数showLoginshowAlert 等)。路由器可以直接注入到 ViewModel 中,您可以调用路由器来显示下一个屏幕,例如,您的 observable 中的 do(onNext) 事件。

    【讨论】:

    【解决方案3】:

    您可以查看is 关键字,它允许您检查对象类型。 More on is keyword。另一种方法是使用type(of: object) 并与UIAlertViewController.self 进行比较

    由于您必须提供 UIAlertViewController 而不是推送它,因此使用 if 和 else 与上面的内容一起呈现如果类型是 UIAlertViewController 并推送否则。注意:没有必要检查 UIViewController,因为它们都是。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-18
      • 2020-10-01
      • 2016-10-20
      • 2016-05-06
      • 1970-01-01
      • 2017-12-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多