在使用 RxSwift 和 mvvm 发出 moya 请求时添加一个微调器,并在用户收到响应时关闭它
Add a spinner on making a moya request using RxSwift and mvvm and dismiss it when user receives a response
我有一个应用程序,我正在尝试使用 MVVM 实现 RxSwift。
我有 SignInViewModel,我正在其中进行验证,我正在使用我正在收听的其余响应布尔值更新登录可观察值。
在控制器中 class 只要验证通过,登录按钮就会启用。
以类似的方式,我希望能够在单击按钮时启动微调器,并在用户收到响应时关闭。
当我尝试从控制器中的视图模型监听 loginObservable 时 class。它没有命中绑定块。
我无法弄清楚问题出在哪里。
任何帮助将不胜感激
以下是我的 SignInViewModel
class SignInViewModel {
let validatedEmail: Observable<Bool>
let validatedPassword: Observable<Bool>
let loginEnabled: Observable<Bool>
let loginObservable: Observable<Bool>
init(username: Observable<String>,
password: Observable<String>,
loginTap: Observable<Void>) {
self.validatedEmail = username
.map { [=10=].characters.count >= 5 }
.shareReplay(1)
self.validatedPassword = password
.map { [=10=].characters.count >= 2 }
.shareReplay(1)
self.loginEnabled = Observable.combineLatest(validatedEmail, validatedPassword ) { [=10=] && }
let userAndPassword = Observable.combineLatest(username, password) {([=10=],)}
self.loginObservable = loginTap.withLatestFrom(userAndPassword).flatMapLatest{ (username, password) in
return RestService.login(username: username, password: password).observeOn(MainScheduler.instance)
}
}
}
下面是moyaRequestclass
final class MoyaRequest{
func signIn(userData: Creator) -> Observable<Response> {
return provider.request(.signIn(userData))
.filter(statusCode: 200)
}
}
以下是我的 RestService class
class RestService:NSObject {
static var moyaRequest = MoyaRequest()
static var disposeBag = DisposeBag()
static func login(username: String, password: String) -> Observable<Bool> {
let userData = Creator()
userData?.username = username
userData?.password = password
print("Username password", userData?.username, userData?.password)
return Observable.create { observer in moyaRequest.signIn(userData: userData!).subscribe{ event -> Void in
switch event {
case .next(let response):
print("Response",response)
case .error(let error):
let moyaError: MoyaError? = error as? MoyaError
let response: Response? = moyaError?.response
let statusCode: Int? = response?.statusCode
print("Sample Response code error" + String(describing: statusCode))
default:
break
}
}
return Disposables.create()
}
}
}
我正在尝试在控制器中绑定视图模型class。
class SignInViewController: UIViewController{
let disposeBag = DisposeBag()
@IBOutlet weak var passwordTextfield: UITextField!
@IBOutlet weak var usernameTextfield: UITextField!
private var viewModel : SignInViewModel!
@IBOutlet weak var signInButton: UIButton!
override func viewDidLoad() {
setUpRxViewModel()
}
func setUpRxViewModel(){
self.viewModel = SignInViewModel(username: self.usernameTextfield.rx.text.orEmpty.asObservable(),
password: self.passwordTextfield.rx.text.orEmpty.asObservable(),
loginTap: self.signInButton.rx.tap.asObservable())
self.viewModel.loginEnabled.bind{ valid in
self.signInButton.isEnabled = valid
}.addDisposableTo(disposeBag)
self.viewModel.loginObservable.bind{ input in
print("Login Clicked")
}.addDisposableTo(disposeBag)
}
}
在您的 login
方法中,您没有向观察者发送任何事件。应该是:
case .next(let response):
observer.on(.next(true))
print("Response",response)
case .error(let error):
observer.on(.error(error))
//or observer.on(.next(false)) if you intend to use Bool as indicator of operation success which is a very bad idea.
let moyaError: MoyaError? = error as? MoyaError
let response: Response? = moyaError?.response
let statusCode: Int? = response?.statusCode
此外,如果您将 Moya 与 RxSwift 一起使用,我建议您在任何地方都使用 RxMoyaProvider
。使用 Observable.create
通常意味着你做错了。
您也不应该在网络请求级别根据状态代码过滤掉事件,因为如果出现问题,您将不会在您的链中收到任何事件。
我有一个应用程序,我正在尝试使用 MVVM 实现 RxSwift。
我有 SignInViewModel,我正在其中进行验证,我正在使用我正在收听的其余响应布尔值更新登录可观察值。
在控制器中 class 只要验证通过,登录按钮就会启用。
以类似的方式,我希望能够在单击按钮时启动微调器,并在用户收到响应时关闭。
当我尝试从控制器中的视图模型监听 loginObservable 时 class。它没有命中绑定块。
我无法弄清楚问题出在哪里。
任何帮助将不胜感激
以下是我的 SignInViewModel
class SignInViewModel {
let validatedEmail: Observable<Bool>
let validatedPassword: Observable<Bool>
let loginEnabled: Observable<Bool>
let loginObservable: Observable<Bool>
init(username: Observable<String>,
password: Observable<String>,
loginTap: Observable<Void>) {
self.validatedEmail = username
.map { [=10=].characters.count >= 5 }
.shareReplay(1)
self.validatedPassword = password
.map { [=10=].characters.count >= 2 }
.shareReplay(1)
self.loginEnabled = Observable.combineLatest(validatedEmail, validatedPassword ) { [=10=] && }
let userAndPassword = Observable.combineLatest(username, password) {([=10=],)}
self.loginObservable = loginTap.withLatestFrom(userAndPassword).flatMapLatest{ (username, password) in
return RestService.login(username: username, password: password).observeOn(MainScheduler.instance)
}
}
}
下面是moyaRequestclass
final class MoyaRequest{
func signIn(userData: Creator) -> Observable<Response> {
return provider.request(.signIn(userData))
.filter(statusCode: 200)
}
}
以下是我的 RestService class
class RestService:NSObject {
static var moyaRequest = MoyaRequest()
static var disposeBag = DisposeBag()
static func login(username: String, password: String) -> Observable<Bool> {
let userData = Creator()
userData?.username = username
userData?.password = password
print("Username password", userData?.username, userData?.password)
return Observable.create { observer in moyaRequest.signIn(userData: userData!).subscribe{ event -> Void in
switch event {
case .next(let response):
print("Response",response)
case .error(let error):
let moyaError: MoyaError? = error as? MoyaError
let response: Response? = moyaError?.response
let statusCode: Int? = response?.statusCode
print("Sample Response code error" + String(describing: statusCode))
default:
break
}
}
return Disposables.create()
}
}
}
我正在尝试在控制器中绑定视图模型class。
class SignInViewController: UIViewController{
let disposeBag = DisposeBag()
@IBOutlet weak var passwordTextfield: UITextField!
@IBOutlet weak var usernameTextfield: UITextField!
private var viewModel : SignInViewModel!
@IBOutlet weak var signInButton: UIButton!
override func viewDidLoad() {
setUpRxViewModel()
}
func setUpRxViewModel(){
self.viewModel = SignInViewModel(username: self.usernameTextfield.rx.text.orEmpty.asObservable(),
password: self.passwordTextfield.rx.text.orEmpty.asObservable(),
loginTap: self.signInButton.rx.tap.asObservable())
self.viewModel.loginEnabled.bind{ valid in
self.signInButton.isEnabled = valid
}.addDisposableTo(disposeBag)
self.viewModel.loginObservable.bind{ input in
print("Login Clicked")
}.addDisposableTo(disposeBag)
}
}
在您的 login
方法中,您没有向观察者发送任何事件。应该是:
case .next(let response):
observer.on(.next(true))
print("Response",response)
case .error(let error):
observer.on(.error(error))
//or observer.on(.next(false)) if you intend to use Bool as indicator of operation success which is a very bad idea.
let moyaError: MoyaError? = error as? MoyaError
let response: Response? = moyaError?.response
let statusCode: Int? = response?.statusCode
此外,如果您将 Moya 与 RxSwift 一起使用,我建议您在任何地方都使用 RxMoyaProvider
。使用 Observable.create
通常意味着你做错了。
您也不应该在网络请求级别根据状态代码过滤掉事件,因为如果出现问题,您将不会在您的链中收到任何事件。