【发布时间】:2019-06-13 12:37:24
【问题描述】:
我在一个应用中有一个场景,我被要求对其进行更改。
我对@987654321@不是很熟悉,所以如果这很明显,请原谅我。
我的视图控制器呈现一个包含登录表单的WKWebView。当用户完成表单时,会发回我当前在WKNavigationDelegate 中打印出来的属性。
我想做的是将该属性传递给我的oauthService,它作为我的ViewModel 中的依赖项存在。
我可以在模型中创建一个方法,例如
func passPropToServie(_ prop: String) {
// do something
}
只是从视图控制器调用它,但我不确定这是否正确,或者'rxswift'的执行方式是什么。
再次抱歉,这是一个我正在使用的应用程序,所以我仍在接受原始代码。
登录协调员
import UIKit
import RxCocoa
import RxSwift
class LoginCoordinator: BaseCoordinator<()> {
typealias Dependencies = HasOAuthService
private let window: UIWindow
private let dependencies: Dependencies
init(window: UIWindow, dependencies: Dependencies) {
self.window = window
self.dependencies = dependencies
}
override func start() -> Observable<()> {
let viewController = LoginViewController()
let avm: Attachable<LoginViewModel> = .detached(dependencies)
let viewModel = viewController.attach(wrapper: avm)
viewModel.loginURL.drive(onNext: { login in
viewController.handle(login?.url)
}).disposed(by: viewController.disposeBag)
window.rootViewController = viewController
window.makeKeyAndVisible()
return viewModel.isLoggedIn
.asObservable()
.filter { $0 }
.map { _ in return }
}
}
LoginViewController
import UIKit
import WebKit
import RxCocoa
import RxSwift
class LoginViewController: UIViewController, ViewModelAttaching {
let disposeBag = DisposeBag()
var viewModel: Attachable<LoginViewModel>!
var bindings: LoginViewModel.Bindings {
return LoginViewModel.Bindings()
}
private var requestURL: URL?
lazy var webView: WKWebView = {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.dataDetectorTypes = [.all]
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.navigationDelegate = self
webView.allowsBackForwardNavigationGestures = false
return webView
}()
override func viewDidLoad() {
super.viewDidLoad()
}
override func loadView() {
view = webView
}
func bind(viewModel: LoginViewModel) -> LoginViewModel {
return viewModel
}
func handle(_ url: URL?) {
guard let url = url else { return }
requestURL = url
webView.load(URLRequest(url: url))
}
}
extension LoginViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if let url = navigationAction.request.url, url.scheme == "homedev", url.valueOf("code") != nil {
print(url)
}
decisionHandler(.allow)
}
}
LoginViewModel
import RxSwift
import RxCocoa
final class LoginViewModel: ViewModelType {
typealias Dependency = HasOAuthService
let isLoggedIn: Driver<Bool>
let loginURL: Driver<URLComponents?>
struct Bindings { }
init(dependency: Dependency, bindings: Bindings) {
isLoggedIn = dependency.oauthService.currentUser
.map { user in return user == true }
.asDriver(onErrorJustReturn: false)
loginURL = dependency.oauthService.loginURL
.map { $0 }
.asDriver(onErrorJustReturn: nil)
}
}
【问题讨论】:
-
如果您获得了对模型的引用,那么只需在其上调用方法就可以了。如果您想根据
oauth的结果更新您的 UI,那么您可以使用 RxSwift/RxCocoa/RxRelay。对于oauth本身,RxSwift 对 IMO 没有多大用处。不过,PromiseKit 可能会让事情变得更容易。就我个人而言,我会用 Promise 封装oauth请求,并根据结果更改我的 UI 绑定/监听的 RxSwift 变量。 -
谢谢,感谢您抽出宝贵时间回答:)