Instantly share code, notes, and snippets.

Embed
What would you like to do?
WKNavigationDelegate+Rx.swift
import Foundation
import RxSwift
import RxCocoa
import WebKit
class WKNavigationDelegateProxy: DelegateProxy, WKNavigationDelegate, DelegateProxyType {
static func currentDelegateFor(object: AnyObject) -> AnyObject? {
let webView: WKWebView = object as! WKWebView
return webView.navigationDelegate
}
static func setCurrentDelegate(delegate: AnyObject?, toObject object: AnyObject) {
let webView: WKWebView = object as! WKWebView
webView.navigationDelegate = delegate as? WKNavigationDelegate
}
}
///
/// WKNavigationDelegate protocol のうち、以下 3 メソッドは RxSwift によって
/// 引数 decisionHandler が NSBlock に変換されるためうまく扱えないので
/// この extension から外しています。
/// - webView(_:didReceiveAuthenticationChallenge:completionHandler:) -> Void
/// - webView(_:decidePolicyForNavigationAction:decisionHandler:) -> Void
/// - webView(_:decidePolicyForNavigationResponse:decisionHandler:) -> Void
///
/// この extention を利用するためには extension 利用側で以下のように実装するか、
/// このファイルの下部にある UIViewController の extention 実装(デフォルト動作になるようにしています)を利用してください。
///
/// ```
/// // viewDidLoad 等の初期化メソッドにて
/// let webView: WKWebView = WKWebView(frame: CGRectZero, configuration: WKWebViewConfiguration())
///
/// override func viewDidLoad() {
/// super.viewDidLoad()
///
/// // この行を追加することで rx_delegate で実装していない protocol があれば self に proxy するようになります
/// webView.rx_delegate.setForwardToDelegate(self, retainDelegate: false)
///
/// // ...
/// }
///
/// override func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
/// // ...
/// }
///
/// // ...
/// ```
///
extension WKWebView {
public var rx_delegate: DelegateProxy {
return proxyForObject(WKNavigationDelegateProxy.self, self)
}
public var rx_didCommitNavigation: Observable<(WKWebView, WKNavigation!)> {
return rx_delegate.observe(#selector(WKNavigationDelegate.webView(_: didCommitNavigation:)))
.map { params in
let webView: WKWebView = params[0] as! WKWebView
let navigation: WKNavigation! = params[1] as! WKNavigation
return (webView, navigation)
}
}
public var rx_didFailNavigation: Observable<(WKWebView, WKNavigation!, NSError)> {
return rx_delegate.observe(#selector(WKNavigationDelegate.webView(_: didFailNavigation: withError:)))
.map { params in
let webView: WKWebView = params[0] as! WKWebView
let navigation: WKNavigation! = params[1] as! WKNavigation
let error: NSError = params[2] as! NSError
return (webView, navigation, error)
}
}
public var rx_didFailProvisionalNavigation: Observable<(WKWebView, WKNavigation!, NSError)> {
return rx_delegate.observe(#selector(WKNavigationDelegate.webView(_: didFailProvisionalNavigation: withError:)))
.map { params in
let webView: WKWebView = params[0] as! WKWebView
let navigation: WKNavigation! = params[1] as! WKNavigation
let error: NSError = params[2] as! NSError
return (webView, navigation, error)
}
}
public var rx_didFinishNavigation: Observable<(WKWebView, WKNavigation!)> {
return rx_delegate.observe(#selector(WKNavigationDelegate.webView(_: didFinishNavigation:)))
.map { params in
let webView: WKWebView = params[0] as! WKWebView
let navigation: WKNavigation! = params[1] as! WKNavigation
return (webView, navigation)
}
}
public var rx_didReceiveServerRedirectForProvisionalNavigation: Observable<(WKWebView, WKNavigation!)> {
return rx_delegate.observe(#selector(WKNavigationDelegate.webView(_: didReceiveServerRedirectForProvisionalNavigation:)))
.map { params in
let webView: WKWebView = params[0] as! WKWebView
let navigation: WKNavigation! = params[1] as! WKNavigation
return (webView, navigation)
}
}
public var rx_didStartProvisionalNavigation: Observable<(WKWebView, WKNavigation!)> {
return rx_delegate.observe(#selector(WKNavigationDelegate.webView(_: didStartProvisionalNavigation:)))
.map { params in
let webView: WKWebView = params[0] as! WKWebView
let navigation: WKNavigation! = params[1] as! WKNavigation
return (webView, navigation)
}
}
public var rx_webContentProcessDidTerminate: Observable<WKWebView> {
return rx_delegate.observe(#selector(WKNavigationDelegate.webViewWebContentProcessDidTerminate(_:)))
.map { params in
let webView: WKWebView = params[0] as! WKWebView
return webView
}
}
}
/// 上記 WKWebView extension の実装をサポートする extension です。
/// WKNavigationDelegate protocol のデフォルト実装を与えます。
/// 実際の UIViewController のサブクラスで同じメソッドが定義されている場合はそちらが優先されます(override 属性つきになります)。
extension UIViewController {
func webView(webView: WKWebView, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
completionHandler(NSURLSessionAuthChallengeDisposition.PerformDefaultHandling, nil)
}
func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
decisionHandler(WKNavigationActionPolicy.Allow)
}
func webView(webView: WKWebView, decidePolicyForNavigationResponse navigationResponse: WKNavigationResponse, decisionHandler: (WKNavigationResponsePolicy) -> Void) {
decisionHandler(WKNavigationResponsePolicy.Allow)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment