RxSwift - 误解了一些概念

时间:2016-05-02 19:52:32

标签: ios swift rx-swift

我是RxSwift的初学者,我正试着从一个简单的登录界面开始。所以我有2个文本字段和一个登录按钮,它绑定到PublishSubject所以每次点击按钮,我都会发送网络请求来执行身份验证。

由于身份验证可能失败,我选择了Driver,因此每次点击按钮都可以重播我的请求。

我有两个版本,我认为是相同的代码,但一个工作,一个不。 我试图了解幕后发生的事情。

这是第一个有效的版本(每次触摸按钮时请求):

let credentials = Driver.combineLatest(email.asDriver(), password.asDriver()) { ($0, $1) }
self.signIn = signInTaps
    .asDriver(onErrorJustReturn: ())
    .withLatestFrom(credentials)
    .flatMapLatest { email, password in // returns Driver<Result<AuthenticateResponse, APIError>>
        return provider.request(.Authenticate(email: email, password: password))
            .filterSuccessfulStatusCodes()
            .mapObject(AuthenticateResponse)
            .map { element -> Result<AuthenticateResponse, APIError> in
                return .Success(element)
            }
            .asDriver { error in
                let e = APIError.fromError(error)
                return Driver<Result<AuthenticateResponse, APIError>>.just(.Failure(e))
            }
            .debug()
    }

这是一个不起作用的(请求仅在第一次点击时触发):

let credentials = Observable.combineLatest(email.asObservable(), password.asObservable()) { ($0, $1) }
self.signIn = signInTaps.asObservable()
    .withLatestFrom(c)
    .flatMapLatest { email, password in // returns Observable<AuthenticateResponse>
        return provider.request(.Authenticate(email: email, password: password))
            .filterSuccessfulStatusCodes()
            .mapObject(AuthenticateResponse)
    }
    .map { element -> Result<AuthenticateResponse, APIError> in // returns Observable<Result<AuthenticateResponse, APIError>>
        return .Success(element)
    }
    .asDriver { error in // returns Driver<Result<AuthenticateResponse, APIError>>
        let e = APIError.fromError(error)
        return Driver<Result<AuthenticateResponse, APIError>>.just(.Failure(e))
    }
    .debug()

有关信息,这是我的属性声明:

let email = Variable("")
let password = Variable("")
let signInTaps = PublishSubject<Void>()    
let signIn: Driver<Result<AuthenticateResponse, APIError>>

1 个答案:

答案 0 :(得分:11)

让我们分解第一个发生的事情(因为它们大致相同):

handlers = [ (dict1, do_stuff_dict1), (dict2, do_stuff_dict2), (dict3, do_stuff_dict3) ]
for whichDict, whichFunc in handlers:
    try:
        val = whichDict[key]
    except KeyError:
        continue
    else:
        whichFunc()
        break
else:
    do_stuff_not_found()
  1. 您正在组合来自// 1. let credentials = Driver.combineLatest(email.asDriver(), password.asDriver()) { ($0, $1) } // 2. self.signIn = signInTaps .asDriver(onErrorJustReturn: ()) // 3. .withLatestFrom(credentials) // 4. .flatMapLatest { email, password in // returns Driver<Result<AuthenticateResponse, APIError>> return provider.request(.Authenticate(email: email, password: password)) .filterSuccessfulStatusCodes() .mapObject(AuthenticateResponse) .map { element -> Result<AuthenticateResponse, APIError> in return .Success(element) } .asDriver { error in let e = APIError.fromError(error) return Driver<Result<AuthenticateResponse, APIError>>.just(.Failure(e)) } .debug() } 的最新信号和密码,并将它们组合成email s的元组。
  2. 这是您的登录信号,是以下所有信号的合成。
  3. 您只需按一下按钮即可将String的最新结果组合在一起。
  4. 每次点击按钮或电子邮件/密码发出时,您将取消当前信号并创建一个新电话信号(使用Moya),按成功状态代码过滤,映射对象以及处理成功和错误。
  5. 除了使用observable而不是驱动程序之外,第二个示例大致相同。检查credentials并查看每次点击按钮时是否收到活动。可能是信号正在释放的某个地方,实际上两个版本之间的唯一区别是使用驱动程序和可观察数据。

    还要记住,使用驱动程序只是一个可观察的语法糖。

    signInTaps

    相同
    let intDriver = sequenceOf(1, 2, 3, 4, 5, 6)
    .asDriver(onErrorJustReturn: 1)
    .map { $0 + 1 }
    .filter { $0 < 5 }
    

    因此,当您使用observables而不是驱动程序时,您将丢失let intObservable = sequenceOf(1, 2, 3, 4, 5, 6) .observeOn(MainScheduler.sharedInstance) .catchErrorJustReturn(1) .map { $0 + 1 } .filter { $0 < 5 } .shareReplay(1) .observeOn。对于驱动程序,您可能只是看到了重放和缓存的值。