You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何映射Single返回的元组响应?RxSwift Driver使用问题求助

问题分析与解决方案

核心问题

  1. checkEmailRequest 使用 map 生成嵌套的 Driver<Driver<(Bool, Bool)>>,导致后续处理冗余且逻辑混乱
  2. requestEmail 仅创建请求序列但未正确订阅/整合到输出流,触发变量未使用警告
  3. 未正确处理API请求的加载状态、跳转逻辑的事件发射逻辑

修正后的代码

class LoginVM: ViewModelType {

    struct Input {
        let emailText: Driver<String>
        let validate: Driver<Void>
    }

    struct Output {
        let loading: Driver<Bool>
        let gotoLoginScreen: Driver<Void>
        let errorNoInternetConnection: Driver<Void>
    }

    private let manageSession: ManageSessionProtocol
    private let manageAccountDetail: ManageAccountDetailProtocol

    init(manageSession: ManageSessionProtocol, manageAccountDetail: ManageAccountDetailProtocol) {
        self.manageSession = manageSession
        self.manageAccountDetail = manageAccountDetail
    }

    func transform(input: Input) -> Output {
        let errorRouter = ErrorRouter()
        let activityIndicator = ActivityIndicator()
        
        // 修正checkEmail请求链:用flatMapLatest展开Driver,避免嵌套结构
        let checkEmailResponse = input.validate
            .withLatestFrom(input.emailText)
            .filter { $0.isValidEmail }
            .flatMapLatest { [weak self] emailText -> Driver<(Bool, Bool)> in
                guard let self else { return Driver.just((false, false)) }
                return self.manageSession.checkEmail(email: emailText)
                    .rerouteError(errorRouter)
                    .trackActivity(activityIndicator)
                    .asDriver(onErrorJustReturn: (false, false))
            }
        
        // 处理"调用API请求"逻辑:元组第一个值为false时执行请求
        let _ = checkEmailResponse
            .filter { !$0.0 }
            .flatMapLatest { [weak self] _ -> Driver<Void> in
                guard let self else { return Driver.empty() }
                return self.manageSession.requestEmailLoginChallenge()
                    .rerouteError(errorRouter)
                    .trackActivity(activityIndicator)
                    .map { _ in () }
                    .asDriver(onErrorJustReturn: ())
            }
            .drive() // 主动订阅执行请求,解决变量未使用警告
        
        // 处理"跳转下一个VC"逻辑:元组第二个值为true时发射跳转事件
        let gotoLoginScreen = checkEmailResponse
            .filter { $0.1 }
            .map { _ in () }
        
        // 统一管理加载状态
        let loading = activityIndicator.asDriver()
        
        // 处理无网络错误事件
        let errorNoInternetConnection = errorRouter.noInternetConnection
            .map { _ in () }
            .asDriver(onErrorJustReturn: ())

        return Output(
            loading: loading,
            gotoLoginScreen: gotoLoginScreen,
            errorNoInternetConnection: errorNoInternetConnection
        )
    }
}

关键修正点

  • 消除嵌套Driver:将 map 替换为 flatMapLatest,直接展开API请求返回的Driver,简化后续逻辑处理
  • 确保请求执行:对API请求序列调用 drive() 主动订阅,既保证请求被执行,又解决变量未使用警告
  • 实现跳转逻辑:通过 filter 筛选符合条件的事件,map 转为Void事件供外部绑定跳转操作
  • 统一加载状态:使用 ActivityIndicator 追踪所有API请求的加载状态,避免重复编写加载逻辑
  • 避免内存泄漏:闭包中使用 [weak self] 打破循环引用

内容的提问来源于stack exchange,提问作者ferryawijayanto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 00:25:25