Я создаю приложение, которое имеет определенный процесс двусторонней аутентификации: во-первых, вход в систему на основе REST с учетными данными, который возвращает конечную точку веб-сокета на сервере, а также авторизационный токен, который используется для подключения к нему.
Только после успешного подключения веб-сокета к серверу, я должен переключиться на следующее представление.
Пытаясь реализовать в MVVM, я создал структуру API для сетевых вызовов сервера:
Мой LoginViewController привязывает имя пользователя и пароль к LoginViewModel, который в свою очередь привязывает действие входа в систему к кнопке входа в систему:
func onLogin() -> CocoaAction {
return CocoaAction { _ in
self.loginService.login(username: self.usernameText.value, password: self.passwordText.value)
let MainViewModel = MainViewModel(sceneCoordinator: self.sceneCoordinator)
return self.sceneCoordinator.transition(to: Scene.mainView(mainViewModel), type: .modal).asObservable().map { _ in }
}
}
Служба LoginService должна вернуть Completable для входа в систему, чтобычтобы указать успешный вход в систему (и переместить представление на главный экран приложения) или ошибку, чтобы показать пользователю.
protocol LoginServiceType {
@discardableResult
func login(username: String, password: String) -> Completable
}
У меня возникла проблема с реализацией этой функции.Сначала он должен вызвать API входа в REST, а после получения ответа запустить соединение с веб-сокетом.Реализация API сервера выглядит следующим образом (в соответствии с рекомендуемыми примерами RxSwift MVVM):
struct Server: ServerProtocol {
// MARK: - API Errors
enum Errors: Error {
case requestFailed
}
// MARK: - API Endpoint requests
static func login(for username: String, password: String) -> Observable<JSONObject> {
let parameters = [
"username": username,
"password": password
]
return request(address: Server.Address.login, parameters: parameters)
}
// MARK: - generic request to API
static private func request<T: Any>(address: Address, parameters: [String: String] = [:]) -> Observable<T> {
return Observable.create { observer in
let request = Alamofire.request(address.url.absoluteString,
method: .post,
parameters: parameters,
encoding: JSONEncoding.default,
headers: nil)
request.responseJSON { response in
guard response.result.isSuccess == true, let data = response.data,
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? T, let result = json else {
observer.onError(Errors.requestFailed)
return
}
observer.onNext(result)
observer.onCompleted()
}
return Disposables.create {
request.cancel()
}
}
}
}
Поэтому я пытаюсь выяснить, как подключить вызов REST, его ответс нужной конечной точкой + токеном для создания Websocket и подписки на обратный вызов подключения, который затем должен вернуть Completable обратно в LoginViewModel.
Любой совет будет приветствоваться.