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

RxSwift中withLatestFrom不兼容BehaviorRelay的问题排查

手机号注册检查ViewModel中withLatestFrom报错问题排查

问题描述

编写用于用户注册前检查手机号状态的ViewModel时,遇到如下错误:

Instance method 'withLatestFrom' requires that 'BehaviorRelay' conform to 'SharedSequenceConvertibleType'

相关代码如下:

import Foundation
import RxSwift
import RxCocoa

protocol RegisterViewModelling {
    var openRegistrationData: Signal<String> { get }
    var showErrorMessage: Signal<String> { get }
    var sendButtonActive: Driver<Bool> { get }
    
    var phoneNumberText: BehaviorRelay<String> { get }
    var tapSendButton: PublishRelay<Void> { get }
}

final class RegisterViewModel: RegisterViewModelling {
    var openRegistrationData: Signal<String>
    let showErrorMessage: Signal<String>
    let sendButtonActive: Driver<Bool>
    let phoneNumberText: BehaviorRelay<String> = BehaviorRelay<String>(value: "")
    let tapSendButton: PublishRelay<Void> = PublishRelay<Void>()
        
    init(getPhoneNumberStatus: GetPhoneNumberStatusUseCase) {
        sendButtonActive = phoneNumberText
            .asDriver(onErrorDriveWith: .empty())
            .map(shouldButtonActive(number:))
        
        let isRegistered = tapSendButton
            .withLatestFrom(phoneNumberText)
            .flatMap(getPhoneNumberStatus.get(number:))
            .share()
        
        showErrorMessage = isRegistered
            .asSignal(onErrorSignalWith: .just(true))
            .filter { $0 == true }
            .map { _ in () }
            .map(getErrorMessage)
        
        openRegistrationData = isRegistered
            .asSignal(onErrorSignalWith: .just(true))
            .filter { $0 == false }
            .withLatestFrom(phoneNumberText) // ERROR: Instance method 'withLatestFrom' requires that 'BehaviorRelay<String>' conform to 'SharedSequenceConvertibleType'
        
    }
}

private func shouldButtonActive(number: String) -> Bool {
    return !number.isEmpty && number.count <= 15
}

private func getErrorMessage() -> String {
    return "Phone number has been registered."
}

protocol GetPhoneNumberStatusUseCase {
    func get(number: String) -> Observable<Bool>
}

问题原因

  1. 序列体系不兼容:报错行中调用withLatestFrom的是Signal类型序列,Signal属于RxSwift的SharedSequence体系,它的withLatestFrom方法要求传入的参数必须符合SharedSequenceConvertibleType协议(比如Driver、Signal这类),而BehaviorRelay本质是Observable的子类,并不直接符合该协议。
  2. 前序代码正常的原因:之前tapSendButton是PublishRelay(属于Observable体系),它的withLatestFrom方法接受ObservableConvertibleType类型参数,BehaviorRelay刚好符合这个协议,因此可以直接传入使用。

解决方法

将BehaviorRelay转换为Signal(或Driver)类型,使其符合SharedSequenceConvertibleType要求,修改报错行代码如下:

.withLatestFrom(phoneNumberText.asSignal(onErrorSignalWith: .empty()))

或者转换为Driver(与上下文Signal兼容):

.withLatestFrom(phoneNumberText.asDriver(onErrorDriveWith: .empty()))

内容的提问来源于stack exchange,提问作者Bawenang Rukmoko Pardian Putra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 11:09:17