【问题标题】:RxSwift - Misundestanding some conceptRxSwift - 误解了一些概念
【发布时间】:2016-05-02 19:52:31
【问题描述】:

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

由于身份验证可能会失败,因此我使用了Driver,以便每次单击按钮时都可以重播我的请求。

我有 2 个版本的我认为是相同的代码,但一个有效,一个无效。 我试图了解幕后发生的事情。

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

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>>

【问题讨论】:

标签: ios swift rx-swift


【解决方案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()
}
  1. 您正在组合来自email 的最新信号和密码,并将它们组合成一个Strings 的元组。
  2. 这是您的登录信号,由以下所有信号组合而成。
  3. 您只需轻按一个按钮即可将来自credentials 的最新结果合并。
  4. 每次点击按钮或发送电子邮件/密码时,您都会取消当前信号并创建一个新信号以进行呼叫(使用 Moya)、按成功状态代码过滤、映射对象并处理成功和错误。

第二个例子基本相同,只是你使用的是 observables 而不是驱动程序。检查signInTaps,看看您是否在每次点击按钮时都收到事件。可能是信号在某个地方被解除分配,而这两个版本之间的唯一区别是驱动程序和 observables 的使用。

还要记住,使用驱动程序只是对 observable 的语法糖。

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

一样
let intObservable = sequenceOf(1, 2, 3, 4, 5, 6)
.observeOn(MainScheduler.sharedInstance)
.catchErrorJustReturn(1)
.map { $0 + 1 }
.filter { $0 < 5 }
.shareReplay(1)

因此,当您使用 observables 而不是驱动程序时,您将失去 .observeOnshareReplay。可能是因为使用驱动程序,您只会看到重播和缓存的值。

【讨论】:

  • 但是所有的 UIKit 信号都不是他们所谓的“热可观察”吗?我的意思是,他们应该一直在发射并且永远不会被释放吗?
  • 此外,在我的第二个示例中,我将所有内容都转换为Driver,所以理论上,信号不应该永远不会被释放吗?
  • 您的登录点击 observable 可能不热,这就是为什么它只能触发一次。我会使用 ReactiveCocoa 而不是 RxSwift,更容易理解。
  • 大家好,我建议您阅读article。为了更好地理解“冷”和“热”的含义
猜你喜欢
  • 2020-08-29
  • 2013-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
相关资源
最近更新 更多