Skip to content

Instantly share code, notes, and snippets.

@yagihiro
Created April 29, 2016 07:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yagihiro/728f6c5afa59ad483a2eb3d55d911e45 to your computer and use it in GitHub Desktop.
Save yagihiro/728f6c5afa59ad483a2eb3d55d911e45 to your computer and use it in GitHub Desktop.
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