ios - rxdatasources - rxswift tableview example
RxSwift-interpretando mal algĂșn concepto (1)
Soy muy principiante con RxSwift y estoy tratando de comenzar con una simple pantalla de inicio de sesión. Así que tengo 2 campos de texto y un botón de inicio de sesión, que está PublishSubject
a un PublishSubject
por lo que cada vez que PublishSubject
el botón, enviaré una solicitud de red para realizar la autenticación.
Como la autenticación puede fallar, me fui con un Driver
para que pudiera reproducir mi solicitud cada vez que hago clic en el botón.
Tengo 2 versiones de lo que creo que es el mismo código, pero una funciona y la otra no. Estoy tratando de entender lo que pasa detrás de la escena.
Aquí la primera versión que funciona (solicite cada vez que toque el botón):
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()
}
Y aquí está el que no funciona (la solicitud se activa solo con el primer clic):
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()
Para información, aquí está mi declaración de propiedades:
let email = Variable("")
let password = Variable("")
let signInTaps = PublishSubject<Void>()
let signIn: Driver<Result<AuthenticateResponse, APIError>>
Analicemos lo que está pasando en el primero (ya que son casi todos iguales):
// 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()
}
- Estás combinando las últimas señales del
email
y la contraseña y las estás combinando en una tupla deString
. - Esta es su señal de inicio de sesión, el compuesto de todas las siguientes señales.
- Estás combinando los últimos resultados de las
credentials
con solo tocar un botón. - Cada vez que se toca el botón o se emite el correo electrónico / contraseña, se cancela la señal actual y se crea una nueva que realiza una llamada (usando Moya), se filtra por códigos de estado exitosos, se asigna el objeto y se controla el éxito y el error.
El segundo ejemplo es casi el mismo, excepto que está usando observables en lugar de controladores. Compruebe signInTaps
y vea si está recibiendo eventos cada vez que toca el botón. Podría ser que en algún lugar de la línea la señal se desasigne y realmente la única diferencia entre las dos versiones es el uso de controladores y observables.
También tenga en cuenta que usar un controlador es solo azúcar sintáctica sobre un observable.
let intDriver = sequenceOf(1, 2, 3, 4, 5, 6)
.asDriver(onErrorJustReturn: 1)
.map { $0 + 1 }
.filter { $0 < 5 }
es lo mismo que
let intObservable = sequenceOf(1, 2, 3, 4, 5, 6)
.observeOn(MainScheduler.sharedInstance)
.catchErrorJustReturn(1)
.map { $0 + 1 }
.filter { $0 < 5 }
.shareReplay(1)
Entonces, cuando usa observables sobre los controladores, está perdiendo .observeOn
y .observeOn
. Podría ser que con los controladores solo esté viendo la reproducción y los valores almacenados en caché.